| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | /* Type object implementation */ | ||
| 2 | |||
| 3 | #include "Python.h" | ||
| 4 | #include "pycore_call.h" | ||
| 5 | #include "pycore_code.h" // CO_FAST_FREE | ||
| 6 | #include "pycore_compile.h" // _Py_Mangle() | ||
| 7 | #include "pycore_initconfig.h" // _PyStatus_OK() | ||
| 8 | #include "pycore_moduleobject.h" // _PyModule_GetDef() | ||
| 9 | #include "pycore_object.h" // _PyType_HasFeature() | ||
| 10 | #include "pycore_pyerrors.h" // _PyErr_Occurred() | ||
| 11 | #include "pycore_pystate.h" // _PyThreadState_GET() | ||
| 12 | #include "pycore_typeobject.h" // struct type_cache | ||
| 13 | #include "pycore_unionobject.h" // _Py_union_type_or | ||
| 14 | #include "pycore_frame.h" // _PyInterpreterFrame | ||
| 15 | #include "opcode.h" // MAKE_CELL | ||
| 16 | #include "structmember.h" // PyMemberDef | ||
| 17 | |||
| 18 | #include <ctype.h> | ||
| 19 | |||
| 20 | /*[clinic input] | ||
| 21 | class type "PyTypeObject *" "&PyType_Type" | ||
| 22 | class object "PyObject *" "&PyBaseObject_Type" | ||
| 23 | [clinic start generated code]*/ | ||
| 24 | /*[clinic end generated code: output=da39a3ee5e6b4b0d input=4b94608d231c434b]*/ | ||
| 25 | |||
| 26 | #include "clinic/typeobject.c.h" | ||
| 27 | |||
| 28 | /* Support type attribute lookup cache */ | ||
| 29 | |||
| 30 | /* The cache can keep references to the names alive for longer than | ||
| 31 | they normally would. This is why the maximum size is limited to | ||
| 32 | MCACHE_MAX_ATTR_SIZE, since it might be a problem if very large | ||
| 33 | strings are used as attribute names. */ | ||
| 34 | #define MCACHE_MAX_ATTR_SIZE 100 | ||
| 35 | #define MCACHE_HASH(version, name_hash) \ | ||
| 36 | (((unsigned int)(version) ^ (unsigned int)(name_hash)) \ | ||
| 37 | & ((1 << MCACHE_SIZE_EXP) - 1)) | ||
| 38 | |||
| 39 | #define MCACHE_HASH_METHOD(type, name) \ | ||
| 40 | MCACHE_HASH((type)->tp_version_tag, ((Py_ssize_t)(name)) >> 3) | ||
| 41 | #define MCACHE_CACHEABLE_NAME(name) \ | ||
| 42 | PyUnicode_CheckExact(name) && \ | ||
| 43 | PyUnicode_IS_READY(name) && \ | ||
| 44 | (PyUnicode_GET_LENGTH(name) <= MCACHE_MAX_ATTR_SIZE) | ||
| 45 | |||
| 46 | // bpo-42745: next_version_tag remains shared by all interpreters because of static types | ||
| 47 | // Used to set PyTypeObject.tp_version_tag | ||
| 48 | static unsigned int next_version_tag = 1; | ||
| 49 | |||
| 50 | typedef struct PySlot_Offset { | ||
| 51 | short subslot_offset; | ||
| 52 | short slot_offset; | ||
| 53 | } PySlot_Offset; | ||
| 54 | |||
| 55 | |||
| 56 | static PyObject * | ||
| 57 | slot_tp_new(PyTypeObject *type, PyObject *args, PyObject *kwds); | ||
| 58 | |||
| 59 | static void | ||
| 60 | clear_slotdefs(void); | ||
| 61 | |||
| 62 | static PyObject * | ||
| 63 | lookup_maybe_method(PyObject *self, PyObject *attr, int *unbound); | ||
| 64 | |||
| 65 | static int | ||
| 66 | slot_tp_setattro(PyObject *self, PyObject *name, PyObject *value); | ||
| 67 | |||
| 68 | /* | ||
| 69 | * finds the beginning of the docstring's introspection signature. | ||
| 70 | * if present, returns a pointer pointing to the first '('. | ||
| 71 | * otherwise returns NULL. | ||
| 72 | * | ||
| 73 | * doesn't guarantee that the signature is valid, only that it | ||
| 74 | * has a valid prefix. (the signature must also pass skip_signature.) | ||
| 75 | */ | ||
| 76 | static const char * | ||
| 77 | 757107 | find_signature(const char *name, const char *doc) | |
| 78 | { | ||
| 79 | const char *dot; | ||
| 80 | size_t length; | ||
| 81 | |||
| 82 |
2/2✓ Branch 0 taken 114 times.
✓ Branch 1 taken 756993 times.
|
757107 | if (!doc) |
| 83 | 114 | return NULL; | |
| 84 | |||
| 85 | assert(name != NULL); | ||
| 86 | |||
| 87 | /* for dotted names like classes, only use the last component */ | ||
| 88 | 756993 | dot = strrchr(name, '.'); | |
| 89 |
2/2✓ Branch 0 taken 401000 times.
✓ Branch 1 taken 355993 times.
|
756993 | if (dot) |
| 90 | 401000 | name = dot + 1; | |
| 91 | |||
| 92 | 756993 | length = strlen(name); | |
| 93 |
2/2✓ Branch 0 taken 438931 times.
✓ Branch 1 taken 318062 times.
|
756993 | if (strncmp(doc, name, length)) |
| 94 | 438931 | return NULL; | |
| 95 | 318062 | doc += length; | |
| 96 |
2/2✓ Branch 0 taken 55992 times.
✓ Branch 1 taken 262070 times.
|
318062 | if (*doc != '(') |
| 97 | 55992 | return NULL; | |
| 98 | 262070 | return doc; | |
| 99 | } | ||
| 100 | |||
| 101 | #define SIGNATURE_END_MARKER ")\n--\n\n" | ||
| 102 | #define SIGNATURE_END_MARKER_LENGTH 6 | ||
| 103 | /* | ||
| 104 | * skips past the end of the docstring's introspection signature. | ||
| 105 | * (assumes doc starts with a valid signature prefix.) | ||
| 106 | */ | ||
| 107 | static const char * | ||
| 108 | 262070 | skip_signature(const char *doc) | |
| 109 | { | ||
| 110 |
2/2✓ Branch 0 taken 14654947 times.
✓ Branch 1 taken 19646 times.
|
14674593 | while (*doc) { |
| 111 |
2/2✓ Branch 0 taken 393265 times.
✓ Branch 1 taken 14261682 times.
|
14654947 | if ((*doc == *SIGNATURE_END_MARKER) && |
| 112 |
2/2✓ Branch 0 taken 148499 times.
✓ Branch 1 taken 244766 times.
|
393265 | !strncmp(doc, SIGNATURE_END_MARKER, SIGNATURE_END_MARKER_LENGTH)) |
| 113 | 148499 | return doc + SIGNATURE_END_MARKER_LENGTH; | |
| 114 |
4/4✓ Branch 0 taken 251954 times.
✓ Branch 1 taken 14254494 times.
✓ Branch 2 taken 93925 times.
✓ Branch 3 taken 158029 times.
|
14506448 | if ((*doc == '\n') && (doc[1] == '\n')) |
| 115 | 93925 | return NULL; | |
| 116 | 14412523 | doc++; | |
| 117 | } | ||
| 118 | 19646 | return NULL; | |
| 119 | } | ||
| 120 | |||
| 121 | int | ||
| 122 | ✗ | _PyType_CheckConsistency(PyTypeObject *type) | |
| 123 | { | ||
| 124 | #define CHECK(expr) \ | ||
| 125 | do { if (!(expr)) { _PyObject_ASSERT_FAILED_MSG((PyObject *)type, Py_STRINGIFY(expr)); } } while (0) | ||
| 126 | |||
| 127 | ✗ | CHECK(!_PyObject_IsFreed((PyObject *)type)); | |
| 128 | |||
| 129 | ✗ | if (!(type->tp_flags & Py_TPFLAGS_READY)) { | |
| 130 | /* don't check static types before PyType_Ready() */ | ||
| 131 | ✗ | return 1; | |
| 132 | } | ||
| 133 | |||
| 134 | ✗ | CHECK(Py_REFCNT(type) >= 1); | |
| 135 | ✗ | CHECK(PyType_Check(type)); | |
| 136 | |||
| 137 | ✗ | CHECK(!(type->tp_flags & Py_TPFLAGS_READYING)); | |
| 138 | ✗ | CHECK(type->tp_dict != NULL); | |
| 139 | |||
| 140 | ✗ | if (type->tp_flags & Py_TPFLAGS_HAVE_GC) { | |
| 141 | // bpo-44263: tp_traverse is required if Py_TPFLAGS_HAVE_GC is set. | ||
| 142 | // Note: tp_clear is optional. | ||
| 143 | ✗ | CHECK(type->tp_traverse != NULL); | |
| 144 | } | ||
| 145 | |||
| 146 | ✗ | if (type->tp_flags & Py_TPFLAGS_DISALLOW_INSTANTIATION) { | |
| 147 | ✗ | CHECK(type->tp_new == NULL); | |
| 148 | ✗ | CHECK(PyDict_Contains(type->tp_dict, &_Py_ID(__new__)) == 0); | |
| 149 | } | ||
| 150 | |||
| 151 | ✗ | return 1; | |
| 152 | #undef CHECK | ||
| 153 | } | ||
| 154 | |||
| 155 | static const char * | ||
| 156 | 757107 | _PyType_DocWithoutSignature(const char *name, const char *internal_doc) | |
| 157 | { | ||
| 158 | 757107 | const char *doc = find_signature(name, internal_doc); | |
| 159 | |||
| 160 |
2/2✓ Branch 0 taken 262070 times.
✓ Branch 1 taken 495037 times.
|
757107 | if (doc) { |
| 161 | 262070 | doc = skip_signature(doc); | |
| 162 |
2/2✓ Branch 0 taken 148499 times.
✓ Branch 1 taken 113571 times.
|
262070 | if (doc) |
| 163 | 148499 | return doc; | |
| 164 | } | ||
| 165 | 608608 | return internal_doc; | |
| 166 | } | ||
| 167 | |||
| 168 | PyObject * | ||
| 169 | 74115 | _PyType_GetDocFromInternalDoc(const char *name, const char *internal_doc) | |
| 170 | { | ||
| 171 | 74115 | const char *doc = _PyType_DocWithoutSignature(name, internal_doc); | |
| 172 | |||
| 173 |
4/4✓ Branch 0 taken 74001 times.
✓ Branch 1 taken 114 times.
✓ Branch 2 taken 141 times.
✓ Branch 3 taken 73860 times.
|
74115 | if (!doc || *doc == '\0') { |
| 174 | 255 | Py_RETURN_NONE; | |
| 175 | } | ||
| 176 | |||
| 177 | 73860 | return PyUnicode_FromString(doc); | |
| 178 | } | ||
| 179 | |||
| 180 | PyObject * | ||
| 181 | ✗ | _PyType_GetTextSignatureFromInternalDoc(const char *name, const char *internal_doc) | |
| 182 | { | ||
| 183 | ✗ | const char *start = find_signature(name, internal_doc); | |
| 184 | const char *end; | ||
| 185 | |||
| 186 | ✗ | if (start) | |
| 187 | ✗ | end = skip_signature(start); | |
| 188 | else | ||
| 189 | ✗ | end = NULL; | |
| 190 | ✗ | if (!end) { | |
| 191 | ✗ | Py_RETURN_NONE; | |
| 192 | } | ||
| 193 | |||
| 194 | /* back "end" up until it points just past the final ')' */ | ||
| 195 | ✗ | end -= SIGNATURE_END_MARKER_LENGTH - 1; | |
| 196 | assert((end - start) >= 2); /* should be "()" at least */ | ||
| 197 | assert(end[-1] == ')'); | ||
| 198 | assert(end[0] == '\n'); | ||
| 199 | ✗ | return PyUnicode_FromStringAndSize(start, end - start); | |
| 200 | } | ||
| 201 | |||
| 202 | |||
| 203 | static struct type_cache* | ||
| 204 | 3699232369 | get_type_cache(void) | |
| 205 | { | ||
| 206 | 3699232369 | PyInterpreterState *interp = _PyInterpreterState_GET(); | |
| 207 | 3699232369 | return &interp->type_cache; | |
| 208 | } | ||
| 209 | |||
| 210 | |||
| 211 | static void | ||
| 212 | 3404 | type_cache_clear(struct type_cache *cache, PyObject *value) | |
| 213 | { | ||
| 214 |
2/2✓ Branch 0 taken 13942784 times.
✓ Branch 1 taken 3404 times.
|
13946188 | for (Py_ssize_t i = 0; i < (1 << MCACHE_SIZE_EXP); i++) { |
| 215 | 13942784 | struct type_cache_entry *entry = &cache->hashtable[i]; | |
| 216 | 13942784 | entry->version = 0; | |
| 217 | 13942784 | Py_XSETREF(entry->name, _Py_XNewRef(value)); | |
| 218 | 13942784 | entry->value = NULL; | |
| 219 | } | ||
| 220 | 3404 | } | |
| 221 | |||
| 222 | |||
| 223 | void | ||
| 224 | 3408 | _PyType_InitCache(PyInterpreterState *interp) | |
| 225 | { | ||
| 226 | 3408 | struct type_cache *cache = &interp->type_cache; | |
| 227 |
2/2✓ Branch 0 taken 13959168 times.
✓ Branch 1 taken 3408 times.
|
13962576 | for (Py_ssize_t i = 0; i < (1 << MCACHE_SIZE_EXP); i++) { |
| 228 | 13959168 | struct type_cache_entry *entry = &cache->hashtable[i]; | |
| 229 | assert(entry->name == NULL); | ||
| 230 | |||
| 231 | 13959168 | entry->version = 0; | |
| 232 | // Set to None so _PyType_Lookup() can use Py_SETREF(), | ||
| 233 | // rather than using slower Py_XSETREF(). | ||
| 234 | 13959168 | entry->name = Py_NewRef(Py_None); | |
| 235 | 13959168 | entry->value = NULL; | |
| 236 | } | ||
| 237 | 3408 | } | |
| 238 | |||
| 239 | |||
| 240 | static unsigned int | ||
| 241 | ✗ | _PyType_ClearCache(PyInterpreterState *interp) | |
| 242 | { | ||
| 243 | ✗ | struct type_cache *cache = &interp->type_cache; | |
| 244 | #if MCACHE_STATS | ||
| 245 | size_t total = cache->hits + cache->collisions + cache->misses; | ||
| 246 | fprintf(stderr, "-- Method cache hits = %zd (%d%%)\n", | ||
| 247 | cache->hits, (int) (100.0 * cache->hits / total)); | ||
| 248 | fprintf(stderr, "-- Method cache true misses = %zd (%d%%)\n", | ||
| 249 | cache->misses, (int) (100.0 * cache->misses / total)); | ||
| 250 | fprintf(stderr, "-- Method cache collisions = %zd (%d%%)\n", | ||
| 251 | cache->collisions, (int) (100.0 * cache->collisions / total)); | ||
| 252 | fprintf(stderr, "-- Method cache size = %zd KiB\n", | ||
| 253 | sizeof(cache->hashtable) / 1024); | ||
| 254 | #endif | ||
| 255 | |||
| 256 | // Set to None, rather than NULL, so _PyType_Lookup() can | ||
| 257 | // use Py_SETREF() rather than using slower Py_XSETREF(). | ||
| 258 | ✗ | type_cache_clear(cache, Py_None); | |
| 259 | |||
| 260 | ✗ | return next_version_tag - 1; | |
| 261 | } | ||
| 262 | |||
| 263 | |||
| 264 | unsigned int | ||
| 265 | ✗ | PyType_ClearCache(void) | |
| 266 | { | ||
| 267 | ✗ | PyInterpreterState *interp = _PyInterpreterState_GET(); | |
| 268 | ✗ | return _PyType_ClearCache(interp); | |
| 269 | } | ||
| 270 | |||
| 271 | |||
| 272 | void | ||
| 273 | 3404 | _PyTypes_Fini(PyInterpreterState *interp) | |
| 274 | { | ||
| 275 | 3404 | struct type_cache *cache = &interp->type_cache; | |
| 276 | 3404 | type_cache_clear(cache, NULL); | |
| 277 |
1/2✓ Branch 1 taken 3404 times.
✗ Branch 2 not taken.
|
3404 | if (_Py_IsMainInterpreter(interp)) { |
| 278 | 3404 | clear_slotdefs(); | |
| 279 | } | ||
| 280 | 3404 | } | |
| 281 | |||
| 282 | |||
| 283 | void | ||
| 284 | 6775759 | PyType_Modified(PyTypeObject *type) | |
| 285 | { | ||
| 286 | /* Invalidate any cached data for the specified type and all | ||
| 287 | subclasses. This function is called after the base | ||
| 288 | classes, mro, or attributes of the type are altered. | ||
| 289 | |||
| 290 | Invariants: | ||
| 291 | |||
| 292 | - before Py_TPFLAGS_VALID_VERSION_TAG can be set on a type, | ||
| 293 | it must first be set on all super types. | ||
| 294 | |||
| 295 | This function clears the Py_TPFLAGS_VALID_VERSION_TAG of a | ||
| 296 | type (so it must first clear it on all subclasses). The | ||
| 297 | tp_version_tag value is meaningless unless this flag is set. | ||
| 298 | We don't assign new version tags eagerly, but only as | ||
| 299 | needed. | ||
| 300 | */ | ||
| 301 |
2/2✓ Branch 1 taken 5058638 times.
✓ Branch 2 taken 1717121 times.
|
6775759 | if (!_PyType_HasFeature(type, Py_TPFLAGS_VALID_VERSION_TAG)) { |
| 302 | 5058638 | return; | |
| 303 | } | ||
| 304 | |||
| 305 | 1717121 | PyObject *subclasses = type->tp_subclasses; | |
| 306 |
2/2✓ Branch 0 taken 179960 times.
✓ Branch 1 taken 1537161 times.
|
1717121 | if (subclasses != NULL) { |
| 307 | assert(PyDict_CheckExact(subclasses)); | ||
| 308 | |||
| 309 | 179960 | Py_ssize_t i = 0; | |
| 310 | PyObject *ref; | ||
| 311 |
2/2✓ Branch 1 taken 488890 times.
✓ Branch 2 taken 179960 times.
|
668850 | while (PyDict_Next(subclasses, &i, NULL, &ref)) { |
| 312 | assert(PyWeakref_CheckRef(ref)); | ||
| 313 | 488890 | PyObject *obj = PyWeakref_GET_OBJECT(ref); | |
| 314 |
2/2✓ Branch 0 taken 460794 times.
✓ Branch 1 taken 28096 times.
|
488890 | if (obj == Py_None) { |
| 315 | 460794 | continue; | |
| 316 | } | ||
| 317 | 28096 | PyType_Modified(_PyType_CAST(obj)); | |
| 318 | } | ||
| 319 | } | ||
| 320 | |||
| 321 | 1717121 | type->tp_flags &= ~Py_TPFLAGS_VALID_VERSION_TAG; | |
| 322 | 1717121 | type->tp_version_tag = 0; /* 0 is not a valid version tag */ | |
| 323 | } | ||
| 324 | |||
| 325 | static void | ||
| 326 | 4978662 | type_mro_modified(PyTypeObject *type, PyObject *bases) { | |
| 327 | /* | ||
| 328 | Check that all base classes or elements of the MRO of type are | ||
| 329 | able to be cached. This function is called after the base | ||
| 330 | classes or mro of the type are altered. | ||
| 331 | |||
| 332 | Unset HAVE_VERSION_TAG and VALID_VERSION_TAG if the type | ||
| 333 | has a custom MRO that includes a type which is not officially | ||
| 334 | super type, or if the type implements its own mro() method. | ||
| 335 | |||
| 336 | Called from mro_internal, which will subsequently be called on | ||
| 337 | each subclass when their mro is recursively updated. | ||
| 338 | */ | ||
| 339 | Py_ssize_t i, n; | ||
| 340 | 4978662 | int custom = !Py_IS_TYPE(type, &PyType_Type); | |
| 341 | int unbound; | ||
| 342 | |||
| 343 |
2/2✓ Branch 0 taken 742950 times.
✓ Branch 1 taken 4235712 times.
|
4978662 | if (custom) { |
| 344 | PyObject *mro_meth, *type_mro_meth; | ||
| 345 | 742950 | mro_meth = lookup_maybe_method( | |
| 346 | (PyObject *)type, &_Py_ID(mro), &unbound); | ||
| 347 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 742950 times.
|
742950 | if (mro_meth == NULL) { |
| 348 | ✗ | goto clear; | |
| 349 | } | ||
| 350 | 742950 | type_mro_meth = lookup_maybe_method( | |
| 351 | (PyObject *)&PyType_Type, &_Py_ID(mro), &unbound); | ||
| 352 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 742950 times.
|
742950 | if (type_mro_meth == NULL) { |
| 353 | ✗ | Py_DECREF(mro_meth); | |
| 354 | ✗ | goto clear; | |
| 355 | } | ||
| 356 | 742950 | int custom_mro = (mro_meth != type_mro_meth); | |
| 357 | 742950 | Py_DECREF(mro_meth); | |
| 358 | 742950 | Py_DECREF(type_mro_meth); | |
| 359 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 742950 times.
|
742950 | if (custom_mro) { |
| 360 | ✗ | goto clear; | |
| 361 | } | ||
| 362 | } | ||
| 363 | 4978662 | n = PyTuple_GET_SIZE(bases); | |
| 364 |
2/2✓ Branch 0 taken 11521063 times.
✓ Branch 1 taken 4978662 times.
|
16499725 | for (i = 0; i < n; i++) { |
| 365 | 11521063 | PyObject *b = PyTuple_GET_ITEM(bases, i); | |
| 366 | 11521063 | PyTypeObject *cls = _PyType_CAST(b); | |
| 367 | |||
| 368 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 11521063 times.
|
11521063 | if (!PyType_IsSubtype(type, cls)) { |
| 369 | ✗ | goto clear; | |
| 370 | } | ||
| 371 | } | ||
| 372 | 4978662 | return; | |
| 373 | ✗ | clear: | |
| 374 | ✗ | type->tp_flags &= ~Py_TPFLAGS_VALID_VERSION_TAG; | |
| 375 | ✗ | type->tp_version_tag = 0; /* 0 is not a valid version tag */ | |
| 376 | } | ||
| 377 | |||
| 378 | static int | ||
| 379 | 65597768 | assign_version_tag(struct type_cache *cache, PyTypeObject *type) | |
| 380 | { | ||
| 381 | /* Ensure that the tp_version_tag is valid and set | ||
| 382 | Py_TPFLAGS_VALID_VERSION_TAG. To respect the invariant, this | ||
| 383 | must first be done on all super classes. Return 0 if this | ||
| 384 | cannot be done, 1 if Py_TPFLAGS_VALID_VERSION_TAG. | ||
| 385 | */ | ||
| 386 |
2/2✓ Branch 1 taken 63613018 times.
✓ Branch 2 taken 1984750 times.
|
65597768 | if (_PyType_HasFeature(type, Py_TPFLAGS_VALID_VERSION_TAG)) { |
| 387 | 63613018 | return 1; | |
| 388 | } | ||
| 389 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 1984750 times.
|
1984750 | if (!_PyType_HasFeature(type, Py_TPFLAGS_READY)) { |
| 390 | ✗ | return 0; | |
| 391 | } | ||
| 392 | |||
| 393 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1984750 times.
|
1984750 | if (next_version_tag == 0) { |
| 394 | /* We have run out of version numbers */ | ||
| 395 | ✗ | return 0; | |
| 396 | } | ||
| 397 | 1984750 | type->tp_version_tag = next_version_tag++; | |
| 398 | assert (type->tp_version_tag != 0); | ||
| 399 | |||
| 400 | 1984750 | PyObject *bases = type->tp_bases; | |
| 401 | 1984750 | Py_ssize_t n = PyTuple_GET_SIZE(bases); | |
| 402 |
2/2✓ Branch 0 taken 2195887 times.
✓ Branch 1 taken 1984750 times.
|
4180637 | for (Py_ssize_t i = 0; i < n; i++) { |
| 403 | 2195887 | PyObject *b = PyTuple_GET_ITEM(bases, i); | |
| 404 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 2195887 times.
|
2195887 | if (!assign_version_tag(cache, _PyType_CAST(b))) |
| 405 | ✗ | return 0; | |
| 406 | } | ||
| 407 | 1984750 | type->tp_flags |= Py_TPFLAGS_VALID_VERSION_TAG; | |
| 408 | 1984750 | return 1; | |
| 409 | } | ||
| 410 | |||
| 411 | |||
| 412 | static PyMemberDef type_members[] = { | ||
| 413 | {"__basicsize__", T_PYSSIZET, offsetof(PyTypeObject,tp_basicsize),READONLY}, | ||
| 414 | {"__itemsize__", T_PYSSIZET, offsetof(PyTypeObject, tp_itemsize), READONLY}, | ||
| 415 | {"__flags__", T_ULONG, offsetof(PyTypeObject, tp_flags), READONLY}, | ||
| 416 | {"__weakrefoffset__", T_PYSSIZET, | ||
| 417 | offsetof(PyTypeObject, tp_weaklistoffset), READONLY}, | ||
| 418 | {"__base__", T_OBJECT, offsetof(PyTypeObject, tp_base), READONLY}, | ||
| 419 | {"__dictoffset__", T_PYSSIZET, | ||
| 420 | offsetof(PyTypeObject, tp_dictoffset), READONLY}, | ||
| 421 | {"__mro__", T_OBJECT, offsetof(PyTypeObject, tp_mro), READONLY}, | ||
| 422 | {0} | ||
| 423 | }; | ||
| 424 | |||
| 425 | static int | ||
| 426 | 115370 | check_set_special_type_attr(PyTypeObject *type, PyObject *value, const char *name) | |
| 427 | { | ||
| 428 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 115370 times.
|
115370 | if (_PyType_HasFeature(type, Py_TPFLAGS_IMMUTABLETYPE)) { |
| 429 | ✗ | PyErr_Format(PyExc_TypeError, | |
| 430 | "cannot set '%s' attribute of immutable type '%s'", | ||
| 431 | name, type->tp_name); | ||
| 432 | ✗ | return 0; | |
| 433 | } | ||
| 434 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 115370 times.
|
115370 | if (!value) { |
| 435 | ✗ | PyErr_Format(PyExc_TypeError, | |
| 436 | "cannot delete '%s' attribute of immutable type '%s'", | ||
| 437 | name, type->tp_name); | ||
| 438 | ✗ | return 0; | |
| 439 | } | ||
| 440 | |||
| 441 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 115370 times.
|
115370 | if (PySys_Audit("object.__setattr__", "OsO", |
| 442 | type, name, value) < 0) { | ||
| 443 | ✗ | return 0; | |
| 444 | } | ||
| 445 | |||
| 446 | 115370 | return 1; | |
| 447 | } | ||
| 448 | |||
| 449 | const char * | ||
| 450 | 646954 | _PyType_Name(PyTypeObject *type) | |
| 451 | { | ||
| 452 | assert(type->tp_name != NULL); | ||
| 453 | 646954 | const char *s = strrchr(type->tp_name, '.'); | |
| 454 |
2/2✓ Branch 0 taken 262767 times.
✓ Branch 1 taken 384187 times.
|
646954 | if (s == NULL) { |
| 455 | 262767 | s = type->tp_name; | |
| 456 | } | ||
| 457 | else { | ||
| 458 | 384187 | s++; | |
| 459 | } | ||
| 460 | 646954 | return s; | |
| 461 | } | ||
| 462 | |||
| 463 | static PyObject * | ||
| 464 | 30094698 | type_name(PyTypeObject *type, void *context) | |
| 465 | { | ||
| 466 |
2/2✓ Branch 0 taken 29742803 times.
✓ Branch 1 taken 351895 times.
|
30094698 | if (type->tp_flags & Py_TPFLAGS_HEAPTYPE) { |
| 467 | 29742803 | PyHeapTypeObject* et = (PyHeapTypeObject*)type; | |
| 468 | |||
| 469 | 29742803 | Py_INCREF(et->ht_name); | |
| 470 | 29742803 | return et->ht_name; | |
| 471 | } | ||
| 472 | else { | ||
| 473 | 351895 | return PyUnicode_FromString(_PyType_Name(type)); | |
| 474 | } | ||
| 475 | } | ||
| 476 | |||
| 477 | static PyObject * | ||
| 478 | 143702 | type_qualname(PyTypeObject *type, void *context) | |
| 479 | { | ||
| 480 |
2/2✓ Branch 0 taken 36003 times.
✓ Branch 1 taken 107699 times.
|
143702 | if (type->tp_flags & Py_TPFLAGS_HEAPTYPE) { |
| 481 | 36003 | PyHeapTypeObject* et = (PyHeapTypeObject*)type; | |
| 482 | 36003 | Py_INCREF(et->ht_qualname); | |
| 483 | 36003 | return et->ht_qualname; | |
| 484 | } | ||
| 485 | else { | ||
| 486 | 107699 | return PyUnicode_FromString(_PyType_Name(type)); | |
| 487 | } | ||
| 488 | } | ||
| 489 | |||
| 490 | static int | ||
| 491 | 1370 | type_set_name(PyTypeObject *type, PyObject *value, void *context) | |
| 492 | { | ||
| 493 | const char *tp_name; | ||
| 494 | Py_ssize_t name_size; | ||
| 495 | |||
| 496 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 1370 times.
|
1370 | if (!check_set_special_type_attr(type, value, "__name__")) |
| 497 | ✗ | return -1; | |
| 498 |
1/2✗ Branch 2 not taken.
✓ Branch 3 taken 1370 times.
|
1370 | if (!PyUnicode_Check(value)) { |
| 499 | ✗ | PyErr_Format(PyExc_TypeError, | |
| 500 | "can only assign string to %s.__name__, not '%s'", | ||
| 501 | ✗ | type->tp_name, Py_TYPE(value)->tp_name); | |
| 502 | ✗ | return -1; | |
| 503 | } | ||
| 504 | |||
| 505 | 1370 | tp_name = PyUnicode_AsUTF8AndSize(value, &name_size); | |
| 506 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1370 times.
|
1370 | if (tp_name == NULL) |
| 507 | ✗ | return -1; | |
| 508 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1370 times.
|
1370 | if (strlen(tp_name) != (size_t)name_size) { |
| 509 | ✗ | PyErr_SetString(PyExc_ValueError, | |
| 510 | "type name must not contain null characters"); | ||
| 511 | ✗ | return -1; | |
| 512 | } | ||
| 513 | |||
| 514 | 1370 | type->tp_name = tp_name; | |
| 515 | 1370 | Py_INCREF(value); | |
| 516 | 1370 | Py_SETREF(((PyHeapTypeObject*)type)->ht_name, value); | |
| 517 | |||
| 518 | 1370 | return 0; | |
| 519 | } | ||
| 520 | |||
| 521 | static int | ||
| 522 | 4655 | type_set_qualname(PyTypeObject *type, PyObject *value, void *context) | |
| 523 | { | ||
| 524 | PyHeapTypeObject* et; | ||
| 525 | |||
| 526 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 4655 times.
|
4655 | if (!check_set_special_type_attr(type, value, "__qualname__")) |
| 527 | ✗ | return -1; | |
| 528 |
1/2✗ Branch 2 not taken.
✓ Branch 3 taken 4655 times.
|
4655 | if (!PyUnicode_Check(value)) { |
| 529 | ✗ | PyErr_Format(PyExc_TypeError, | |
| 530 | "can only assign string to %s.__qualname__, not '%s'", | ||
| 531 | ✗ | type->tp_name, Py_TYPE(value)->tp_name); | |
| 532 | ✗ | return -1; | |
| 533 | } | ||
| 534 | |||
| 535 | 4655 | et = (PyHeapTypeObject*)type; | |
| 536 | 4655 | Py_INCREF(value); | |
| 537 | 4655 | Py_SETREF(et->ht_qualname, value); | |
| 538 | 4655 | return 0; | |
| 539 | } | ||
| 540 | |||
| 541 | static PyObject * | ||
| 542 | 205966 | type_module(PyTypeObject *type, void *context) | |
| 543 | { | ||
| 544 | PyObject *mod; | ||
| 545 | |||
| 546 |
2/2✓ Branch 0 taken 25330 times.
✓ Branch 1 taken 180636 times.
|
205966 | if (type->tp_flags & Py_TPFLAGS_HEAPTYPE) { |
| 547 | 25330 | mod = PyDict_GetItemWithError(type->tp_dict, &_Py_ID(__module__)); | |
| 548 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 25330 times.
|
25330 | if (mod == NULL) { |
| 549 | ✗ | if (!PyErr_Occurred()) { | |
| 550 | ✗ | PyErr_Format(PyExc_AttributeError, "__module__"); | |
| 551 | } | ||
| 552 | ✗ | return NULL; | |
| 553 | } | ||
| 554 | 25330 | Py_INCREF(mod); | |
| 555 | } | ||
| 556 | else { | ||
| 557 | 180636 | const char *s = strrchr(type->tp_name, '.'); | |
| 558 |
2/2✓ Branch 0 taken 102111 times.
✓ Branch 1 taken 78525 times.
|
180636 | if (s != NULL) { |
| 559 | 204222 | mod = PyUnicode_FromStringAndSize( | |
| 560 | 102111 | type->tp_name, (Py_ssize_t)(s - type->tp_name)); | |
| 561 |
1/2✓ Branch 0 taken 102111 times.
✗ Branch 1 not taken.
|
102111 | if (mod != NULL) |
| 562 | 102111 | PyUnicode_InternInPlace(&mod); | |
| 563 | } | ||
| 564 | else { | ||
| 565 | 78525 | mod = &_Py_ID(builtins); | |
| 566 | 78525 | Py_INCREF(mod); | |
| 567 | } | ||
| 568 | } | ||
| 569 | 205966 | return mod; | |
| 570 | } | ||
| 571 | |||
| 572 | static int | ||
| 573 | 96581 | type_set_module(PyTypeObject *type, PyObject *value, void *context) | |
| 574 | { | ||
| 575 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 96581 times.
|
96581 | if (!check_set_special_type_attr(type, value, "__module__")) |
| 576 | ✗ | return -1; | |
| 577 | |||
| 578 | 96581 | PyType_Modified(type); | |
| 579 | |||
| 580 | 96581 | return PyDict_SetItem(type->tp_dict, &_Py_ID(__module__), value); | |
| 581 | } | ||
| 582 | |||
| 583 | static PyObject * | ||
| 584 | 294319 | type_abstractmethods(PyTypeObject *type, void *context) | |
| 585 | { | ||
| 586 | 294319 | PyObject *mod = NULL; | |
| 587 | /* type itself has an __abstractmethods__ descriptor (this). Don't return | ||
| 588 | that. */ | ||
| 589 |
1/2✓ Branch 0 taken 294319 times.
✗ Branch 1 not taken.
|
294319 | if (type != &PyType_Type) |
| 590 | 294319 | mod = PyDict_GetItemWithError(type->tp_dict, | |
| 591 | &_Py_ID(__abstractmethods__)); | ||
| 592 |
2/2✓ Branch 0 taken 67499 times.
✓ Branch 1 taken 226820 times.
|
294319 | if (!mod) { |
| 593 |
1/2✓ Branch 1 taken 67499 times.
✗ Branch 2 not taken.
|
67499 | if (!PyErr_Occurred()) { |
| 594 | 67499 | PyErr_SetObject(PyExc_AttributeError, &_Py_ID(__abstractmethods__)); | |
| 595 | } | ||
| 596 | 67499 | return NULL; | |
| 597 | } | ||
| 598 | 226820 | Py_INCREF(mod); | |
| 599 | 226820 | return mod; | |
| 600 | } | ||
| 601 | |||
| 602 | static int | ||
| 603 | 240651 | type_set_abstractmethods(PyTypeObject *type, PyObject *value, void *context) | |
| 604 | { | ||
| 605 | /* __abstractmethods__ should only be set once on a type, in | ||
| 606 | abc.ABCMeta.__new__, so this function doesn't do anything | ||
| 607 | special to update subclasses. | ||
| 608 | */ | ||
| 609 | int abstract, res; | ||
| 610 |
1/2✓ Branch 0 taken 240651 times.
✗ Branch 1 not taken.
|
240651 | if (value != NULL) { |
| 611 | 240651 | abstract = PyObject_IsTrue(value); | |
| 612 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 240651 times.
|
240651 | if (abstract < 0) |
| 613 | ✗ | return -1; | |
| 614 | 240651 | res = PyDict_SetItem(type->tp_dict, &_Py_ID(__abstractmethods__), value); | |
| 615 | } | ||
| 616 | else { | ||
| 617 | ✗ | abstract = 0; | |
| 618 | ✗ | res = PyDict_DelItem(type->tp_dict, &_Py_ID(__abstractmethods__)); | |
| 619 | ✗ | if (res && PyErr_ExceptionMatches(PyExc_KeyError)) { | |
| 620 | ✗ | PyErr_SetObject(PyExc_AttributeError, &_Py_ID(__abstractmethods__)); | |
| 621 | ✗ | return -1; | |
| 622 | } | ||
| 623 | } | ||
| 624 |
1/2✓ Branch 0 taken 240651 times.
✗ Branch 1 not taken.
|
240651 | if (res == 0) { |
| 625 | 240651 | PyType_Modified(type); | |
| 626 |
2/2✓ Branch 0 taken 91328 times.
✓ Branch 1 taken 149323 times.
|
240651 | if (abstract) |
| 627 | 91328 | type->tp_flags |= Py_TPFLAGS_IS_ABSTRACT; | |
| 628 | else | ||
| 629 | 149323 | type->tp_flags &= ~Py_TPFLAGS_IS_ABSTRACT; | |
| 630 | } | ||
| 631 | 240651 | return res; | |
| 632 | } | ||
| 633 | |||
| 634 | static PyObject * | ||
| 635 | 377213 | type_get_bases(PyTypeObject *type, void *context) | |
| 636 | { | ||
| 637 | 377213 | Py_INCREF(type->tp_bases); | |
| 638 | 377213 | return type->tp_bases; | |
| 639 | } | ||
| 640 | |||
| 641 | static PyTypeObject *best_base(PyObject *); | ||
| 642 | static int mro_internal(PyTypeObject *, PyObject **); | ||
| 643 | static int type_is_subtype_base_chain(PyTypeObject *, PyTypeObject *); | ||
| 644 | static int compatible_for_assignment(PyTypeObject *, PyTypeObject *, const char *); | ||
| 645 | static int add_subclass(PyTypeObject*, PyTypeObject*); | ||
| 646 | static int add_all_subclasses(PyTypeObject *type, PyObject *bases); | ||
| 647 | static void remove_subclass(PyTypeObject *, PyTypeObject *); | ||
| 648 | static void remove_all_subclasses(PyTypeObject *type, PyObject *bases); | ||
| 649 | static void update_all_slots(PyTypeObject *); | ||
| 650 | |||
| 651 | typedef int (*update_callback)(PyTypeObject *, void *); | ||
| 652 | static int update_subclasses(PyTypeObject *type, PyObject *attr_name, | ||
| 653 | update_callback callback, void *data); | ||
| 654 | static int recurse_down_subclasses(PyTypeObject *type, PyObject *name, | ||
| 655 | update_callback callback, void *data); | ||
| 656 | |||
| 657 | static int | ||
| 658 | 4655 | mro_hierarchy(PyTypeObject *type, PyObject *temp) | |
| 659 | { | ||
| 660 | PyObject *old_mro; | ||
| 661 | 4655 | int res = mro_internal(type, &old_mro); | |
| 662 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4655 times.
|
4655 | if (res <= 0) { |
| 663 | /* error / reentrance */ | ||
| 664 | ✗ | return res; | |
| 665 | } | ||
| 666 | 4655 | PyObject *new_mro = type->tp_mro; | |
| 667 | |||
| 668 | PyObject *tuple; | ||
| 669 |
1/2✓ Branch 0 taken 4655 times.
✗ Branch 1 not taken.
|
4655 | if (old_mro != NULL) { |
| 670 | 4655 | tuple = PyTuple_Pack(3, type, new_mro, old_mro); | |
| 671 | } | ||
| 672 | else { | ||
| 673 | ✗ | tuple = PyTuple_Pack(2, type, new_mro); | |
| 674 | } | ||
| 675 | |||
| 676 |
1/2✓ Branch 0 taken 4655 times.
✗ Branch 1 not taken.
|
4655 | if (tuple != NULL) { |
| 677 | 4655 | res = PyList_Append(temp, tuple); | |
| 678 | } | ||
| 679 | else { | ||
| 680 | ✗ | res = -1; | |
| 681 | } | ||
| 682 | 4655 | Py_XDECREF(tuple); | |
| 683 | |||
| 684 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4655 times.
|
4655 | if (res < 0) { |
| 685 | ✗ | type->tp_mro = old_mro; | |
| 686 | ✗ | Py_DECREF(new_mro); | |
| 687 | ✗ | return -1; | |
| 688 | } | ||
| 689 | 4655 | Py_XDECREF(old_mro); | |
| 690 | |||
| 691 | // Avoid creating an empty list if there is no subclass | ||
| 692 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4655 times.
|
4655 | if (type->tp_subclasses != NULL) { |
| 693 | /* Obtain a copy of subclasses list to iterate over. | ||
| 694 | |||
| 695 | Otherwise type->tp_subclasses might be altered | ||
| 696 | in the middle of the loop, for example, through a custom mro(), | ||
| 697 | by invoking type_set_bases on some subclass of the type | ||
| 698 | which in turn calls remove_subclass/add_subclass on this type. | ||
| 699 | |||
| 700 | Finally, this makes things simple avoiding the need to deal | ||
| 701 | with dictionary iterators and weak references. | ||
| 702 | */ | ||
| 703 | ✗ | PyObject *subclasses = _PyType_GetSubclasses(type); | |
| 704 | ✗ | if (subclasses == NULL) { | |
| 705 | ✗ | return -1; | |
| 706 | } | ||
| 707 | |||
| 708 | ✗ | Py_ssize_t n = PyList_GET_SIZE(subclasses); | |
| 709 | ✗ | for (Py_ssize_t i = 0; i < n; i++) { | |
| 710 | ✗ | PyTypeObject *subclass = _PyType_CAST(PyList_GET_ITEM(subclasses, i)); | |
| 711 | ✗ | res = mro_hierarchy(subclass, temp); | |
| 712 | ✗ | if (res < 0) { | |
| 713 | ✗ | break; | |
| 714 | } | ||
| 715 | } | ||
| 716 | ✗ | Py_DECREF(subclasses); | |
| 717 | } | ||
| 718 | |||
| 719 | 4655 | return res; | |
| 720 | } | ||
| 721 | |||
| 722 | static int | ||
| 723 | 4655 | type_set_bases(PyTypeObject *type, PyObject *new_bases, void *context) | |
| 724 | { | ||
| 725 | // Check arguments | ||
| 726 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 4655 times.
|
4655 | if (!check_set_special_type_attr(type, new_bases, "__bases__")) { |
| 727 | ✗ | return -1; | |
| 728 | } | ||
| 729 | assert(new_bases != NULL); | ||
| 730 | |||
| 731 |
1/2✗ Branch 2 not taken.
✓ Branch 3 taken 4655 times.
|
4655 | if (!PyTuple_Check(new_bases)) { |
| 732 | ✗ | PyErr_Format(PyExc_TypeError, | |
| 733 | "can only assign tuple to %s.__bases__, not %s", | ||
| 734 | ✗ | type->tp_name, Py_TYPE(new_bases)->tp_name); | |
| 735 | ✗ | return -1; | |
| 736 | } | ||
| 737 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 4655 times.
|
4655 | if (PyTuple_GET_SIZE(new_bases) == 0) { |
| 738 | ✗ | PyErr_Format(PyExc_TypeError, | |
| 739 | "can only assign non-empty tuple to %s.__bases__, not ()", | ||
| 740 | type->tp_name); | ||
| 741 | ✗ | return -1; | |
| 742 | } | ||
| 743 | 4655 | Py_ssize_t n = PyTuple_GET_SIZE(new_bases); | |
| 744 |
2/2✓ Branch 0 taken 4655 times.
✓ Branch 1 taken 4655 times.
|
9310 | for (Py_ssize_t i = 0; i < n; i++) { |
| 745 | 4655 | PyObject *ob = PyTuple_GET_ITEM(new_bases, i); | |
| 746 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 4655 times.
|
4655 | if (!PyType_Check(ob)) { |
| 747 | ✗ | PyErr_Format(PyExc_TypeError, | |
| 748 | "%s.__bases__ must be tuple of classes, not '%s'", | ||
| 749 | ✗ | type->tp_name, Py_TYPE(ob)->tp_name); | |
| 750 | ✗ | return -1; | |
| 751 | } | ||
| 752 | 4655 | PyTypeObject *base = (PyTypeObject*)ob; | |
| 753 | |||
| 754 |
1/2✓ Branch 1 taken 4655 times.
✗ Branch 2 not taken.
|
4655 | if (PyType_IsSubtype(base, type) || |
| 755 | /* In case of reentering here again through a custom mro() | ||
| 756 | the above check is not enough since it relies on | ||
| 757 | base->tp_mro which would gonna be updated inside | ||
| 758 | mro_internal only upon returning from the mro(). | ||
| 759 | |||
| 760 | However, base->tp_base has already been assigned (see | ||
| 761 | below), which in turn may cause an inheritance cycle | ||
| 762 | through tp_base chain. And this is definitely | ||
| 763 | not what you want to ever happen. */ | ||
| 764 |
2/4✓ Branch 0 taken 4655 times.
✗ Branch 1 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 4655 times.
|
4655 | (base->tp_mro != NULL && type_is_subtype_base_chain(base, type))) |
| 765 | { | ||
| 766 | ✗ | PyErr_SetString(PyExc_TypeError, | |
| 767 | "a __bases__ item causes an inheritance cycle"); | ||
| 768 | ✗ | return -1; | |
| 769 | } | ||
| 770 | } | ||
| 771 | |||
| 772 | // Compute the new MRO and the new base class | ||
| 773 | 4655 | PyTypeObject *new_base = best_base(new_bases); | |
| 774 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4655 times.
|
4655 | if (new_base == NULL) |
| 775 | ✗ | return -1; | |
| 776 | |||
| 777 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 4655 times.
|
4655 | if (!compatible_for_assignment(type->tp_base, new_base, "__bases__")) { |
| 778 | ✗ | return -1; | |
| 779 | } | ||
| 780 | |||
| 781 | 4655 | PyObject *old_bases = type->tp_bases; | |
| 782 | assert(old_bases != NULL); | ||
| 783 | 4655 | PyTypeObject *old_base = type->tp_base; | |
| 784 | |||
| 785 | 4655 | type->tp_bases = Py_NewRef(new_bases); | |
| 786 | 4655 | type->tp_base = (PyTypeObject *)Py_NewRef(new_base); | |
| 787 | |||
| 788 | 4655 | PyObject *temp = PyList_New(0); | |
| 789 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4655 times.
|
4655 | if (temp == NULL) { |
| 790 | ✗ | goto bail; | |
| 791 | } | ||
| 792 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 4655 times.
|
4655 | if (mro_hierarchy(type, temp) < 0) { |
| 793 | ✗ | goto undo; | |
| 794 | } | ||
| 795 | 4655 | Py_DECREF(temp); | |
| 796 | |||
| 797 | /* Take no action in case if type->tp_bases has been replaced | ||
| 798 | through reentrance. */ | ||
| 799 | int res; | ||
| 800 |
1/2✓ Branch 0 taken 4655 times.
✗ Branch 1 not taken.
|
4655 | if (type->tp_bases == new_bases) { |
| 801 | /* any base that was in __bases__ but now isn't, we | ||
| 802 | need to remove |type| from its tp_subclasses. | ||
| 803 | conversely, any class now in __bases__ that wasn't | ||
| 804 | needs to have |type| added to its subclasses. */ | ||
| 805 | |||
| 806 | /* for now, sod that: just remove from all old_bases, | ||
| 807 | add to all new_bases */ | ||
| 808 | 4655 | remove_all_subclasses(type, old_bases); | |
| 809 | 4655 | res = add_all_subclasses(type, new_bases); | |
| 810 | 4655 | update_all_slots(type); | |
| 811 | } | ||
| 812 | else { | ||
| 813 | ✗ | res = 0; | |
| 814 | } | ||
| 815 | |||
| 816 | 4655 | Py_DECREF(old_bases); | |
| 817 | 4655 | Py_DECREF(old_base); | |
| 818 | |||
| 819 | assert(_PyType_CheckConsistency(type)); | ||
| 820 | 4655 | return res; | |
| 821 | |||
| 822 | ✗ | undo: | |
| 823 | ✗ | n = PyList_GET_SIZE(temp); | |
| 824 | ✗ | for (Py_ssize_t i = n - 1; i >= 0; i--) { | |
| 825 | PyTypeObject *cls; | ||
| 826 | ✗ | PyObject *new_mro, *old_mro = NULL; | |
| 827 | |||
| 828 | ✗ | PyArg_UnpackTuple(PyList_GET_ITEM(temp, i), | |
| 829 | "", 2, 3, &cls, &new_mro, &old_mro); | ||
| 830 | /* Do not rollback if cls has a newer version of MRO. */ | ||
| 831 | ✗ | if (cls->tp_mro == new_mro) { | |
| 832 | ✗ | Py_XINCREF(old_mro); | |
| 833 | ✗ | cls->tp_mro = old_mro; | |
| 834 | ✗ | Py_DECREF(new_mro); | |
| 835 | } | ||
| 836 | } | ||
| 837 | ✗ | Py_DECREF(temp); | |
| 838 | |||
| 839 | ✗ | bail: | |
| 840 | ✗ | if (type->tp_bases == new_bases) { | |
| 841 | assert(type->tp_base == new_base); | ||
| 842 | |||
| 843 | ✗ | type->tp_bases = old_bases; | |
| 844 | ✗ | type->tp_base = old_base; | |
| 845 | |||
| 846 | ✗ | Py_DECREF(new_bases); | |
| 847 | ✗ | Py_DECREF(new_base); | |
| 848 | } | ||
| 849 | else { | ||
| 850 | ✗ | Py_DECREF(old_bases); | |
| 851 | ✗ | Py_DECREF(old_base); | |
| 852 | } | ||
| 853 | |||
| 854 | assert(_PyType_CheckConsistency(type)); | ||
| 855 | ✗ | return -1; | |
| 856 | } | ||
| 857 | |||
| 858 | static PyObject * | ||
| 859 | 3374873 | type_dict(PyTypeObject *type, void *context) | |
| 860 | { | ||
| 861 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3374873 times.
|
3374873 | if (type->tp_dict == NULL) { |
| 862 | ✗ | Py_RETURN_NONE; | |
| 863 | } | ||
| 864 | 3374873 | return PyDictProxy_New(type->tp_dict); | |
| 865 | } | ||
| 866 | |||
| 867 | static PyObject * | ||
| 868 | 65859 | type_get_doc(PyTypeObject *type, void *context) | |
| 869 | { | ||
| 870 | PyObject *result; | ||
| 871 |
3/4✓ Branch 0 taken 55428 times.
✓ Branch 1 taken 10431 times.
✓ Branch 2 taken 55428 times.
✗ Branch 3 not taken.
|
65859 | if (!(type->tp_flags & Py_TPFLAGS_HEAPTYPE) && type->tp_doc != NULL) { |
| 872 | 55428 | return _PyType_GetDocFromInternalDoc(type->tp_name, type->tp_doc); | |
| 873 | } | ||
| 874 | 10431 | result = PyDict_GetItemWithError(type->tp_dict, &_Py_ID(__doc__)); | |
| 875 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 10431 times.
|
10431 | if (result == NULL) { |
| 876 | ✗ | if (!PyErr_Occurred()) { | |
| 877 | ✗ | result = Py_None; | |
| 878 | ✗ | Py_INCREF(result); | |
| 879 | } | ||
| 880 | } | ||
| 881 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 10431 times.
|
10431 | else if (Py_TYPE(result)->tp_descr_get) { |
| 882 | ✗ | result = Py_TYPE(result)->tp_descr_get(result, NULL, | |
| 883 | (PyObject *)type); | ||
| 884 | } | ||
| 885 | else { | ||
| 886 | 10431 | Py_INCREF(result); | |
| 887 | } | ||
| 888 | 10431 | return result; | |
| 889 | } | ||
| 890 | |||
| 891 | static PyObject * | ||
| 892 | ✗ | type_get_text_signature(PyTypeObject *type, void *context) | |
| 893 | { | ||
| 894 | ✗ | return _PyType_GetTextSignatureFromInternalDoc(type->tp_name, type->tp_doc); | |
| 895 | } | ||
| 896 | |||
| 897 | static int | ||
| 898 | 8109 | type_set_doc(PyTypeObject *type, PyObject *value, void *context) | |
| 899 | { | ||
| 900 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 8109 times.
|
8109 | if (!check_set_special_type_attr(type, value, "__doc__")) |
| 901 | ✗ | return -1; | |
| 902 | 8109 | PyType_Modified(type); | |
| 903 | 8109 | return PyDict_SetItem(type->tp_dict, &_Py_ID(__doc__), value); | |
| 904 | } | ||
| 905 | |||
| 906 | static PyObject * | ||
| 907 | 44731 | type_get_annotations(PyTypeObject *type, void *context) | |
| 908 | { | ||
| 909 |
2/2✓ Branch 0 taken 41790 times.
✓ Branch 1 taken 2941 times.
|
44731 | if (!(type->tp_flags & Py_TPFLAGS_HEAPTYPE)) { |
| 910 | 41790 | PyErr_Format(PyExc_AttributeError, "type object '%s' has no attribute '__annotations__'", type->tp_name); | |
| 911 | 41790 | return NULL; | |
| 912 | } | ||
| 913 | |||
| 914 | PyObject *annotations; | ||
| 915 | /* there's no _PyDict_GetItemId without WithError, so let's LBYL. */ | ||
| 916 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 2941 times.
|
2941 | if (PyDict_Contains(type->tp_dict, &_Py_ID(__annotations__))) { |
| 917 | ✗ | annotations = PyDict_GetItemWithError( | |
| 918 | type->tp_dict, &_Py_ID(__annotations__)); | ||
| 919 | /* | ||
| 920 | ** PyDict_GetItemWithError could still fail, | ||
| 921 | ** for instance with a well-timed Ctrl-C or a MemoryError. | ||
| 922 | ** so let's be totally safe. | ||
| 923 | */ | ||
| 924 | ✗ | if (annotations) { | |
| 925 | ✗ | if (Py_TYPE(annotations)->tp_descr_get) { | |
| 926 | ✗ | annotations = Py_TYPE(annotations)->tp_descr_get( | |
| 927 | annotations, NULL, (PyObject *)type); | ||
| 928 | } else { | ||
| 929 | ✗ | Py_INCREF(annotations); | |
| 930 | } | ||
| 931 | } | ||
| 932 | } else { | ||
| 933 | 2941 | annotations = PyDict_New(); | |
| 934 |
1/2✓ Branch 0 taken 2941 times.
✗ Branch 1 not taken.
|
2941 | if (annotations) { |
| 935 | 2941 | int result = PyDict_SetItem( | |
| 936 | type->tp_dict, &_Py_ID(__annotations__), annotations); | ||
| 937 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2941 times.
|
2941 | if (result) { |
| 938 | ✗ | Py_CLEAR(annotations); | |
| 939 | } else { | ||
| 940 | 2941 | PyType_Modified(type); | |
| 941 | } | ||
| 942 | } | ||
| 943 | } | ||
| 944 | 2941 | return annotations; | |
| 945 | } | ||
| 946 | |||
| 947 | static int | ||
| 948 | 4655 | type_set_annotations(PyTypeObject *type, PyObject *value, void *context) | |
| 949 | { | ||
| 950 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 4655 times.
|
4655 | if (_PyType_HasFeature(type, Py_TPFLAGS_IMMUTABLETYPE)) { |
| 951 | ✗ | PyErr_Format(PyExc_TypeError, | |
| 952 | "cannot set '__annotations__' attribute of immutable type '%s'", | ||
| 953 | type->tp_name); | ||
| 954 | ✗ | return -1; | |
| 955 | } | ||
| 956 | |||
| 957 | int result; | ||
| 958 |
1/2✓ Branch 0 taken 4655 times.
✗ Branch 1 not taken.
|
4655 | if (value != NULL) { |
| 959 | /* set */ | ||
| 960 | 4655 | result = PyDict_SetItem(type->tp_dict, &_Py_ID(__annotations__), value); | |
| 961 | } else { | ||
| 962 | /* delete */ | ||
| 963 | ✗ | if (!PyDict_Contains(type->tp_dict, &_Py_ID(__annotations__))) { | |
| 964 | ✗ | PyErr_Format(PyExc_AttributeError, "__annotations__"); | |
| 965 | ✗ | return -1; | |
| 966 | } | ||
| 967 | ✗ | result = PyDict_DelItem(type->tp_dict, &_Py_ID(__annotations__)); | |
| 968 | } | ||
| 969 | |||
| 970 |
1/2✓ Branch 0 taken 4655 times.
✗ Branch 1 not taken.
|
4655 | if (result == 0) { |
| 971 | 4655 | PyType_Modified(type); | |
| 972 | } | ||
| 973 | 4655 | return result; | |
| 974 | } | ||
| 975 | |||
| 976 | |||
| 977 | /*[clinic input] | ||
| 978 | type.__instancecheck__ -> bool | ||
| 979 | |||
| 980 | instance: object | ||
| 981 | / | ||
| 982 | |||
| 983 | Check if an object is an instance. | ||
| 984 | [clinic start generated code]*/ | ||
| 985 | |||
| 986 | static int | ||
| 987 | 37088592 | type___instancecheck___impl(PyTypeObject *self, PyObject *instance) | |
| 988 | /*[clinic end generated code: output=08b6bf5f591c3618 input=cdbfeaee82c01a0f]*/ | ||
| 989 | { | ||
| 990 | 37088592 | return _PyObject_RealIsInstance(instance, (PyObject *)self); | |
| 991 | } | ||
| 992 | |||
| 993 | /*[clinic input] | ||
| 994 | type.__subclasscheck__ -> bool | ||
| 995 | |||
| 996 | subclass: object | ||
| 997 | / | ||
| 998 | |||
| 999 | Check if a class is a subclass. | ||
| 1000 | [clinic start generated code]*/ | ||
| 1001 | |||
| 1002 | static int | ||
| 1003 | 3262575 | type___subclasscheck___impl(PyTypeObject *self, PyObject *subclass) | |
| 1004 | /*[clinic end generated code: output=97a4e51694500941 input=071b2ca9e03355f4]*/ | ||
| 1005 | { | ||
| 1006 | 3262575 | return _PyObject_RealIsSubclass(subclass, (PyObject *)self); | |
| 1007 | } | ||
| 1008 | |||
| 1009 | |||
| 1010 | static PyGetSetDef type_getsets[] = { | ||
| 1011 | {"__name__", (getter)type_name, (setter)type_set_name, NULL}, | ||
| 1012 | {"__qualname__", (getter)type_qualname, (setter)type_set_qualname, NULL}, | ||
| 1013 | {"__bases__", (getter)type_get_bases, (setter)type_set_bases, NULL}, | ||
| 1014 | {"__module__", (getter)type_module, (setter)type_set_module, NULL}, | ||
| 1015 | {"__abstractmethods__", (getter)type_abstractmethods, | ||
| 1016 | (setter)type_set_abstractmethods, NULL}, | ||
| 1017 | {"__dict__", (getter)type_dict, NULL, NULL}, | ||
| 1018 | {"__doc__", (getter)type_get_doc, (setter)type_set_doc, NULL}, | ||
| 1019 | {"__text_signature__", (getter)type_get_text_signature, NULL, NULL}, | ||
| 1020 | {"__annotations__", (getter)type_get_annotations, (setter)type_set_annotations, NULL}, | ||
| 1021 | {0} | ||
| 1022 | }; | ||
| 1023 | |||
| 1024 | static PyObject * | ||
| 1025 | 22 | type_repr(PyTypeObject *type) | |
| 1026 | { | ||
| 1027 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 22 times.
|
22 | if (type->tp_name == NULL) { |
| 1028 | // type_repr() called before the type is fully initialized | ||
| 1029 | // by PyType_Ready(). | ||
| 1030 | ✗ | return PyUnicode_FromFormat("<class at %p>", type); | |
| 1031 | } | ||
| 1032 | |||
| 1033 | PyObject *mod, *name, *rtn; | ||
| 1034 | |||
| 1035 | 22 | mod = type_module(type, NULL); | |
| 1036 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 22 times.
|
22 | if (mod == NULL) |
| 1037 | ✗ | PyErr_Clear(); | |
| 1038 |
1/2✗ Branch 2 not taken.
✓ Branch 3 taken 22 times.
|
22 | else if (!PyUnicode_Check(mod)) { |
| 1039 | ✗ | Py_DECREF(mod); | |
| 1040 | ✗ | mod = NULL; | |
| 1041 | } | ||
| 1042 | 22 | name = type_qualname(type, NULL); | |
| 1043 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 22 times.
|
22 | if (name == NULL) { |
| 1044 | ✗ | Py_XDECREF(mod); | |
| 1045 | ✗ | return NULL; | |
| 1046 | } | ||
| 1047 | |||
| 1048 |
2/4✓ Branch 0 taken 22 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 22 times.
✗ Branch 4 not taken.
|
22 | if (mod != NULL && !_PyUnicode_Equal(mod, &_Py_ID(builtins))) |
| 1049 | 22 | rtn = PyUnicode_FromFormat("<class '%U.%U'>", mod, name); | |
| 1050 | else | ||
| 1051 | ✗ | rtn = PyUnicode_FromFormat("<class '%s'>", type->tp_name); | |
| 1052 | |||
| 1053 | 22 | Py_XDECREF(mod); | |
| 1054 | 22 | Py_DECREF(name); | |
| 1055 | 22 | return rtn; | |
| 1056 | } | ||
| 1057 | |||
| 1058 | static PyObject * | ||
| 1059 | 309407796 | type_call(PyTypeObject *type, PyObject *args, PyObject *kwds) | |
| 1060 | { | ||
| 1061 | PyObject *obj; | ||
| 1062 | 309407796 | PyThreadState *tstate = _PyThreadState_GET(); | |
| 1063 | |||
| 1064 | #ifdef Py_DEBUG | ||
| 1065 | /* type_call() must not be called with an exception set, | ||
| 1066 | because it can clear it (directly or indirectly) and so the | ||
| 1067 | caller loses its exception */ | ||
| 1068 | assert(!_PyErr_Occurred(tstate)); | ||
| 1069 | #endif | ||
| 1070 | |||
| 1071 | /* Special case: type(x) should return Py_TYPE(x) */ | ||
| 1072 | /* We only want type itself to accept the one-argument form (#27157) */ | ||
| 1073 |
2/2✓ Branch 0 taken 1243231 times.
✓ Branch 1 taken 308164565 times.
|
309407796 | if (type == &PyType_Type) { |
| 1074 | assert(args != NULL && PyTuple_Check(args)); | ||
| 1075 | assert(kwds == NULL || PyDict_Check(kwds)); | ||
| 1076 | 1243231 | Py_ssize_t nargs = PyTuple_GET_SIZE(args); | |
| 1077 | |||
| 1078 |
1/6✗ Branch 0 not taken.
✓ Branch 1 taken 1243231 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
|
1243231 | if (nargs == 1 && (kwds == NULL || !PyDict_GET_SIZE(kwds))) { |
| 1079 | ✗ | obj = (PyObject *) Py_TYPE(PyTuple_GET_ITEM(args, 0)); | |
| 1080 | ✗ | Py_INCREF(obj); | |
| 1081 | ✗ | return obj; | |
| 1082 | } | ||
| 1083 | |||
| 1084 | /* SF bug 475327 -- if that didn't trigger, we need 3 | ||
| 1085 | arguments. But PyArg_ParseTuple in type_new may give | ||
| 1086 | a msg saying type() needs exactly 3. */ | ||
| 1087 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1243231 times.
|
1243231 | if (nargs != 3) { |
| 1088 | ✗ | PyErr_SetString(PyExc_TypeError, | |
| 1089 | "type() takes 1 or 3 arguments"); | ||
| 1090 | ✗ | return NULL; | |
| 1091 | } | ||
| 1092 | } | ||
| 1093 | |||
| 1094 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 309407796 times.
|
309407796 | if (type->tp_new == NULL) { |
| 1095 | ✗ | _PyErr_Format(tstate, PyExc_TypeError, | |
| 1096 | "cannot create '%s' instances", type->tp_name); | ||
| 1097 | ✗ | return NULL; | |
| 1098 | } | ||
| 1099 | |||
| 1100 | 309407796 | obj = type->tp_new(type, args, kwds); | |
| 1101 | 309407796 | obj = _Py_CheckFunctionResult(tstate, (PyObject*)type, obj, NULL); | |
| 1102 |
2/2✓ Branch 0 taken 19374 times.
✓ Branch 1 taken 309388422 times.
|
309407796 | if (obj == NULL) |
| 1103 | 19374 | return NULL; | |
| 1104 | |||
| 1105 | /* If the returned object is not an instance of type, | ||
| 1106 | it won't be initialized. */ | ||
| 1107 |
2/2✓ Branch 1 taken 4228439 times.
✓ Branch 2 taken 305159983 times.
|
309388422 | if (!PyObject_TypeCheck(obj, type)) |
| 1108 | 4228439 | return obj; | |
| 1109 | |||
| 1110 | 305159983 | type = Py_TYPE(obj); | |
| 1111 |
1/2✓ Branch 0 taken 305159983 times.
✗ Branch 1 not taken.
|
305159983 | if (type->tp_init != NULL) { |
| 1112 | 305159983 | int res = type->tp_init(obj, args, kwds); | |
| 1113 |
2/2✓ Branch 0 taken 353320 times.
✓ Branch 1 taken 304806663 times.
|
305159983 | if (res < 0) { |
| 1114 | assert(_PyErr_Occurred(tstate)); | ||
| 1115 | 353320 | Py_DECREF(obj); | |
| 1116 | 353320 | obj = NULL; | |
| 1117 | } | ||
| 1118 | else { | ||
| 1119 | assert(!_PyErr_Occurred(tstate)); | ||
| 1120 | } | ||
| 1121 | } | ||
| 1122 | 305159983 | return obj; | |
| 1123 | } | ||
| 1124 | |||
| 1125 | PyObject * | ||
| 1126 | 423249493 | _PyType_AllocNoTrack(PyTypeObject *type, Py_ssize_t nitems) | |
| 1127 | { | ||
| 1128 | PyObject *obj; | ||
| 1129 | 423249493 | const size_t size = _PyObject_VAR_SIZE(type, nitems+1); | |
| 1130 | /* note that we need to add one, for the sentinel */ | ||
| 1131 | |||
| 1132 | 423249493 | const size_t presize = _PyType_PreHeaderSize(type); | |
| 1133 | 423249493 | char *alloc = PyObject_Malloc(size + presize); | |
| 1134 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 423249493 times.
|
423249493 | if (alloc == NULL) { |
| 1135 | ✗ | return PyErr_NoMemory(); | |
| 1136 | } | ||
| 1137 | 423249493 | obj = (PyObject *)(alloc + presize); | |
| 1138 |
2/2✓ Branch 0 taken 422072582 times.
✓ Branch 1 taken 1176911 times.
|
423249493 | if (presize) { |
| 1139 | 422072582 | ((PyObject **)alloc)[0] = NULL; | |
| 1140 | 422072582 | ((PyObject **)alloc)[1] = NULL; | |
| 1141 | 422072582 | _PyObject_GC_Link(obj); | |
| 1142 | } | ||
| 1143 | 423249493 | memset(obj, '\0', size); | |
| 1144 | |||
| 1145 |
2/2✓ Branch 0 taken 415657561 times.
✓ Branch 1 taken 7591932 times.
|
423249493 | if (type->tp_itemsize == 0) { |
| 1146 | 415657561 | _PyObject_Init(obj, type); | |
| 1147 | } | ||
| 1148 | else { | ||
| 1149 | 7591932 | _PyObject_InitVar((PyVarObject *)obj, type, nitems); | |
| 1150 | } | ||
| 1151 | 423249493 | return obj; | |
| 1152 | } | ||
| 1153 | |||
| 1154 | PyObject * | ||
| 1155 | 419651486 | PyType_GenericAlloc(PyTypeObject *type, Py_ssize_t nitems) | |
| 1156 | { | ||
| 1157 | 419651486 | PyObject *obj = _PyType_AllocNoTrack(type, nitems); | |
| 1158 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 419651486 times.
|
419651486 | if (obj == NULL) { |
| 1159 | ✗ | return NULL; | |
| 1160 | } | ||
| 1161 | |||
| 1162 |
2/2✓ Branch 1 taken 418474575 times.
✓ Branch 2 taken 1176911 times.
|
419651486 | if (_PyType_IS_GC(type)) { |
| 1163 | 418474575 | _PyObject_GC_TRACK(obj); | |
| 1164 | } | ||
| 1165 | 419651486 | return obj; | |
| 1166 | } | ||
| 1167 | |||
| 1168 | PyObject * | ||
| 1169 | 30217096 | PyType_GenericNew(PyTypeObject *type, PyObject *args, PyObject *kwds) | |
| 1170 | { | ||
| 1171 | 30217096 | return type->tp_alloc(type, 0); | |
| 1172 | } | ||
| 1173 | |||
| 1174 | /* Helpers for subtyping */ | ||
| 1175 | |||
| 1176 | static int | ||
| 1177 | 313940054 | traverse_slots(PyTypeObject *type, PyObject *self, visitproc visit, void *arg) | |
| 1178 | { | ||
| 1179 | Py_ssize_t i, n; | ||
| 1180 | PyMemberDef *mp; | ||
| 1181 | |||
| 1182 | 313940054 | n = Py_SIZE(type); | |
| 1183 | 313940054 | mp = _PyHeapType_GET_MEMBERS((PyHeapTypeObject *)type); | |
| 1184 |
2/2✓ Branch 0 taken 1835436174 times.
✓ Branch 1 taken 313940054 times.
|
2149376228 | for (i = 0; i < n; i++, mp++) { |
| 1185 |
1/2✓ Branch 0 taken 1835436174 times.
✗ Branch 1 not taken.
|
1835436174 | if (mp->type == T_OBJECT_EX) { |
| 1186 | 1835436174 | char *addr = (char *)self + mp->offset; | |
| 1187 | 1835436174 | PyObject *obj = *(PyObject **)addr; | |
| 1188 |
2/2✓ Branch 0 taken 1833039068 times.
✓ Branch 1 taken 2397106 times.
|
1835436174 | if (obj != NULL) { |
| 1189 | 1833039068 | int err = visit(obj, arg); | |
| 1190 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1833039068 times.
|
1833039068 | if (err) |
| 1191 | ✗ | return err; | |
| 1192 | } | ||
| 1193 | } | ||
| 1194 | } | ||
| 1195 | 313940054 | return 0; | |
| 1196 | } | ||
| 1197 | |||
| 1198 | static int | ||
| 1199 | 429224840 | subtype_traverse(PyObject *self, visitproc visit, void *arg) | |
| 1200 | { | ||
| 1201 | PyTypeObject *type, *base; | ||
| 1202 | traverseproc basetraverse; | ||
| 1203 | |||
| 1204 | /* Find the nearest base with a different tp_traverse, | ||
| 1205 | and traverse slots while we're at it */ | ||
| 1206 | 429224840 | type = Py_TYPE(self); | |
| 1207 | 429224840 | base = type; | |
| 1208 |
2/2✓ Branch 0 taken 523654949 times.
✓ Branch 1 taken 429224840 times.
|
952879789 | while ((basetraverse = base->tp_traverse) == subtype_traverse) { |
| 1209 |
2/2✓ Branch 1 taken 313940054 times.
✓ Branch 2 taken 209714895 times.
|
523654949 | if (Py_SIZE(base)) { |
| 1210 | 313940054 | int err = traverse_slots(base, self, visit, arg); | |
| 1211 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 313940054 times.
|
313940054 | if (err) |
| 1212 | ✗ | return err; | |
| 1213 | } | ||
| 1214 | 523654949 | base = base->tp_base; | |
| 1215 | assert(base); | ||
| 1216 | } | ||
| 1217 | |||
| 1218 |
2/2✓ Branch 0 taken 88780848 times.
✓ Branch 1 taken 340443992 times.
|
429224840 | if (type->tp_flags & Py_TPFLAGS_MANAGED_DICT) { |
| 1219 | assert(type->tp_dictoffset); | ||
| 1220 | 88780848 | int err = _PyObject_VisitInstanceAttributes(self, visit, arg); | |
| 1221 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 88780848 times.
|
88780848 | if (err) { |
| 1222 | ✗ | return err; | |
| 1223 | } | ||
| 1224 | } | ||
| 1225 | |||
| 1226 |
2/2✓ Branch 0 taken 96350014 times.
✓ Branch 1 taken 332874826 times.
|
429224840 | if (type->tp_dictoffset != base->tp_dictoffset) { |
| 1227 | 96350014 | PyObject **dictptr = _PyObject_DictPointer(self); | |
| 1228 |
3/4✓ Branch 0 taken 96350014 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 13896260 times.
✓ Branch 3 taken 82453754 times.
|
96350014 | if (dictptr && *dictptr) |
| 1229 |
2/4✓ Branch 0 taken 13896260 times.
✗ Branch 1 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 13896260 times.
|
13896260 | Py_VISIT(*dictptr); |
| 1230 | } | ||
| 1231 | |||
| 1232 |
1/2✓ Branch 0 taken 429224840 times.
✗ Branch 1 not taken.
|
429224840 | if (type->tp_flags & Py_TPFLAGS_HEAPTYPE |
| 1233 |
4/4✓ Branch 0 taken 51929586 times.
✓ Branch 1 taken 377295254 times.
✓ Branch 2 taken 49580534 times.
✓ Branch 3 taken 2349052 times.
|
429224840 | && (!basetraverse || !(base->tp_flags & Py_TPFLAGS_HEAPTYPE))) { |
| 1234 | /* For a heaptype, the instances count as references | ||
| 1235 | to the type. Traverse the type so the collector | ||
| 1236 | can find cycles involving this link. | ||
| 1237 | Skip this visit if basetraverse belongs to a heap type: in that | ||
| 1238 | case, basetraverse will visit the type when we call it later. | ||
| 1239 | */ | ||
| 1240 |
2/4✓ Branch 0 taken 426875788 times.
✗ Branch 1 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 426875788 times.
|
426875788 | Py_VISIT(type); |
| 1241 | } | ||
| 1242 | |||
| 1243 |
2/2✓ Branch 0 taken 51929586 times.
✓ Branch 1 taken 377295254 times.
|
429224840 | if (basetraverse) |
| 1244 | 51929586 | return basetraverse(self, visit, arg); | |
| 1245 | 377295254 | return 0; | |
| 1246 | } | ||
| 1247 | |||
| 1248 | static void | ||
| 1249 | 114092086 | clear_slots(PyTypeObject *type, PyObject *self) | |
| 1250 | { | ||
| 1251 | Py_ssize_t i, n; | ||
| 1252 | PyMemberDef *mp; | ||
| 1253 | |||
| 1254 | 114092086 | n = Py_SIZE(type); | |
| 1255 | 114092086 | mp = _PyHeapType_GET_MEMBERS((PyHeapTypeObject *)type); | |
| 1256 |
2/2✓ Branch 0 taken 508184465 times.
✓ Branch 1 taken 114092086 times.
|
622276551 | for (i = 0; i < n; i++, mp++) { |
| 1257 |
2/4✓ Branch 0 taken 508184465 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 508184465 times.
✗ Branch 3 not taken.
|
508184465 | if (mp->type == T_OBJECT_EX && !(mp->flags & READONLY)) { |
| 1258 | 508184465 | char *addr = (char *)self + mp->offset; | |
| 1259 | 508184465 | PyObject *obj = *(PyObject **)addr; | |
| 1260 |
2/2✓ Branch 0 taken 502050880 times.
✓ Branch 1 taken 6133585 times.
|
508184465 | if (obj != NULL) { |
| 1261 | 502050880 | *(PyObject **)addr = NULL; | |
| 1262 | 502050880 | Py_DECREF(obj); | |
| 1263 | } | ||
| 1264 | } | ||
| 1265 | } | ||
| 1266 | 114092086 | } | |
| 1267 | |||
| 1268 | static int | ||
| 1269 | 2645996 | subtype_clear(PyObject *self) | |
| 1270 | { | ||
| 1271 | PyTypeObject *type, *base; | ||
| 1272 | inquiry baseclear; | ||
| 1273 | |||
| 1274 | /* Find the nearest base with a different tp_clear | ||
| 1275 | and clear slots while we're at it */ | ||
| 1276 | 2645996 | type = Py_TYPE(self); | |
| 1277 | 2645996 | base = type; | |
| 1278 |
2/2✓ Branch 0 taken 4626610 times.
✓ Branch 1 taken 2645996 times.
|
7272606 | while ((baseclear = base->tp_clear) == subtype_clear) { |
| 1279 |
2/2✓ Branch 1 taken 404134 times.
✓ Branch 2 taken 4222476 times.
|
4626610 | if (Py_SIZE(base)) |
| 1280 | 404134 | clear_slots(base, self); | |
| 1281 | 4626610 | base = base->tp_base; | |
| 1282 | assert(base); | ||
| 1283 | } | ||
| 1284 | |||
| 1285 | /* Clear the instance dict (if any), to break cycles involving only | ||
| 1286 | __dict__ slots (as in the case 'self.__dict__ is self'). */ | ||
| 1287 |
2/2✓ Branch 0 taken 1355092 times.
✓ Branch 1 taken 1290904 times.
|
2645996 | if (type->tp_flags & Py_TPFLAGS_MANAGED_DICT) { |
| 1288 | 1355092 | _PyObject_ClearInstanceAttributes(self); | |
| 1289 | } | ||
| 1290 |
2/2✓ Branch 0 taken 1451407 times.
✓ Branch 1 taken 1194589 times.
|
2645996 | if (type->tp_dictoffset != base->tp_dictoffset) { |
| 1291 | 1451407 | PyObject **dictptr = _PyObject_DictPointer(self); | |
| 1292 |
3/4✓ Branch 0 taken 1451407 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 499683 times.
✓ Branch 3 taken 951724 times.
|
1451407 | if (dictptr && *dictptr) |
| 1293 |
1/2✓ Branch 0 taken 499683 times.
✗ Branch 1 not taken.
|
499683 | Py_CLEAR(*dictptr); |
| 1294 | } | ||
| 1295 | |||
| 1296 |
2/2✓ Branch 0 taken 799605 times.
✓ Branch 1 taken 1846391 times.
|
2645996 | if (baseclear) |
| 1297 | 799605 | return baseclear(self); | |
| 1298 | 1846391 | return 0; | |
| 1299 | } | ||
| 1300 | |||
| 1301 | static void | ||
| 1302 | 204008329 | subtype_dealloc(PyObject *self) | |
| 1303 | { | ||
| 1304 | PyTypeObject *type, *base; | ||
| 1305 | destructor basedealloc; | ||
| 1306 | int has_finalizer; | ||
| 1307 | |||
| 1308 | /* Extract the type; we expect it to be a heap type */ | ||
| 1309 | 204008329 | type = Py_TYPE(self); | |
| 1310 | _PyObject_ASSERT((PyObject *)type, type->tp_flags & Py_TPFLAGS_HEAPTYPE); | ||
| 1311 | |||
| 1312 | /* Test whether the type has GC exactly once */ | ||
| 1313 | |||
| 1314 |
2/2✓ Branch 1 taken 878 times.
✓ Branch 2 taken 204007451 times.
|
204008329 | if (!_PyType_IS_GC(type)) { |
| 1315 | /* A non GC dynamic type allows certain simplifications: | ||
| 1316 | there's no need to call clear_slots(), or DECREF the dict, | ||
| 1317 | or clear weakrefs. */ | ||
| 1318 | |||
| 1319 | /* Maybe call finalizer; exit early if resurrected */ | ||
| 1320 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 878 times.
|
878 | if (type->tp_finalize) { |
| 1321 | ✗ | if (PyObject_CallFinalizerFromDealloc(self) < 0) | |
| 1322 | ✗ | return; | |
| 1323 | } | ||
| 1324 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 878 times.
|
878 | if (type->tp_del) { |
| 1325 | ✗ | type->tp_del(self); | |
| 1326 | ✗ | if (Py_REFCNT(self) > 0) { | |
| 1327 | ✗ | return; | |
| 1328 | } | ||
| 1329 | } | ||
| 1330 | |||
| 1331 | /* Find the nearest base with a different tp_dealloc */ | ||
| 1332 | 878 | base = type; | |
| 1333 |
2/2✓ Branch 0 taken 878 times.
✓ Branch 1 taken 878 times.
|
1756 | while ((basedealloc = base->tp_dealloc) == subtype_dealloc) { |
| 1334 | 878 | base = base->tp_base; | |
| 1335 | assert(base); | ||
| 1336 | } | ||
| 1337 | |||
| 1338 | /* Extract the type again; tp_del may have changed it */ | ||
| 1339 | 878 | type = Py_TYPE(self); | |
| 1340 | |||
| 1341 | // Don't read type memory after calling basedealloc() since basedealloc() | ||
| 1342 | // can deallocate the type and free its memory. | ||
| 1343 | 1756 | int type_needs_decref = (type->tp_flags & Py_TPFLAGS_HEAPTYPE | |
| 1344 |
2/4✓ Branch 0 taken 878 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 878 times.
|
878 | && !(base->tp_flags & Py_TPFLAGS_HEAPTYPE)); |
| 1345 | |||
| 1346 | assert((type->tp_flags & Py_TPFLAGS_MANAGED_DICT) == 0); | ||
| 1347 | |||
| 1348 | /* Call the base tp_dealloc() */ | ||
| 1349 | assert(basedealloc); | ||
| 1350 | 878 | basedealloc(self); | |
| 1351 | |||
| 1352 | /* Can't reference self beyond this point. It's possible tp_del switched | ||
| 1353 | our type from a HEAPTYPE to a non-HEAPTYPE, so be careful about | ||
| 1354 | reference counting. Only decref if the base type is not already a heap | ||
| 1355 | allocated type. Otherwise, basedealloc should have decref'd it already */ | ||
| 1356 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 878 times.
|
878 | if (type_needs_decref) { |
| 1357 | ✗ | Py_DECREF(type); | |
| 1358 | } | ||
| 1359 | |||
| 1360 | /* Done */ | ||
| 1361 | 878 | return; | |
| 1362 | } | ||
| 1363 | |||
| 1364 | /* We get here only if the type has GC */ | ||
| 1365 | |||
| 1366 | /* UnTrack and re-Track around the trashcan macro, alas */ | ||
| 1367 | /* See explanation at end of function for full disclosure */ | ||
| 1368 | 204007451 | PyObject_GC_UnTrack(self); | |
| 1369 |
3/4✓ Branch 1 taken 204007451 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 380 times.
✓ Branch 6 taken 204007071 times.
|
204007451 | Py_TRASHCAN_BEGIN(self, subtype_dealloc); |
| 1370 | |||
| 1371 | /* Find the nearest base with a different tp_dealloc */ | ||
| 1372 | 204007071 | base = type; | |
| 1373 |
2/2✓ Branch 0 taken 397717631 times.
✓ Branch 1 taken 204007071 times.
|
601724702 | while ((/*basedealloc =*/ base->tp_dealloc) == subtype_dealloc) { |
| 1374 | 397717631 | base = base->tp_base; | |
| 1375 | assert(base); | ||
| 1376 | } | ||
| 1377 | |||
| 1378 |
3/4✓ Branch 0 taken 200825523 times.
✓ Branch 1 taken 3181548 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 200825523 times.
|
204007071 | has_finalizer = type->tp_finalize || type->tp_del; |
| 1379 | |||
| 1380 |
2/2✓ Branch 0 taken 3181548 times.
✓ Branch 1 taken 200825523 times.
|
204007071 | if (type->tp_finalize) { |
| 1381 | 3181548 | _PyObject_GC_TRACK(self); | |
| 1382 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 3181548 times.
|
3181548 | if (PyObject_CallFinalizerFromDealloc(self) < 0) { |
| 1383 | /* Resurrected */ | ||
| 1384 | ✗ | goto endlabel; | |
| 1385 | } | ||
| 1386 | 3181548 | _PyObject_GC_UNTRACK(self); | |
| 1387 | } | ||
| 1388 | /* | ||
| 1389 | If we added a weaklist, we clear it. Do this *before* calling tp_del, | ||
| 1390 | clearing slots, or clearing the instance dict. | ||
| 1391 | |||
| 1392 | GC tracking must be off at this point. weakref callbacks (if any, and | ||
| 1393 | whether directly here or indirectly in something we call) may trigger GC, | ||
| 1394 | and if self is tracked at that point, it will look like trash to GC and GC | ||
| 1395 | will try to delete self again. | ||
| 1396 | */ | ||
| 1397 |
4/4✓ Branch 0 taken 141631368 times.
✓ Branch 1 taken 62375703 times.
✓ Branch 2 taken 138160529 times.
✓ Branch 3 taken 3470839 times.
|
204007071 | if (type->tp_weaklistoffset && !base->tp_weaklistoffset) { |
| 1398 | 138160529 | PyObject_ClearWeakRefs(self); | |
| 1399 | } | ||
| 1400 | |||
| 1401 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 204007071 times.
|
204007071 | if (type->tp_del) { |
| 1402 | ✗ | _PyObject_GC_TRACK(self); | |
| 1403 | ✗ | type->tp_del(self); | |
| 1404 | ✗ | if (Py_REFCNT(self) > 0) { | |
| 1405 | /* Resurrected */ | ||
| 1406 | ✗ | goto endlabel; | |
| 1407 | } | ||
| 1408 | ✗ | _PyObject_GC_UNTRACK(self); | |
| 1409 | } | ||
| 1410 |
2/2✓ Branch 0 taken 3181548 times.
✓ Branch 1 taken 200825523 times.
|
204007071 | if (has_finalizer) { |
| 1411 | /* New weakrefs could be created during the finalizer call. | ||
| 1412 | If this occurs, clear them out without calling their | ||
| 1413 | finalizers since they might rely on part of the object | ||
| 1414 | being finalized that has already been destroyed. */ | ||
| 1415 |
3/4✓ Branch 0 taken 3181548 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 35132 times.
✓ Branch 3 taken 3146416 times.
|
3181548 | if (type->tp_weaklistoffset && !base->tp_weaklistoffset) { |
| 1416 | /* Modeled after GET_WEAKREFS_LISTPTR() */ | ||
| 1417 | PyWeakReference **list = (PyWeakReference **) \ | ||
| 1418 | 35132 | _PyObject_GET_WEAKREFS_LISTPTR(self); | |
| 1419 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 35132 times.
|
35132 | while (*list) |
| 1420 | ✗ | _PyWeakref_ClearRef(*list); | |
| 1421 | } | ||
| 1422 | } | ||
| 1423 | |||
| 1424 | /* Clear slots up to the nearest base with a different tp_dealloc */ | ||
| 1425 | 204007071 | base = type; | |
| 1426 |
2/2✓ Branch 0 taken 397717631 times.
✓ Branch 1 taken 204007071 times.
|
601724702 | while ((basedealloc = base->tp_dealloc) == subtype_dealloc) { |
| 1427 |
2/2✓ Branch 1 taken 113687952 times.
✓ Branch 2 taken 284029679 times.
|
397717631 | if (Py_SIZE(base)) |
| 1428 | 113687952 | clear_slots(base, self); | |
| 1429 | 397717631 | base = base->tp_base; | |
| 1430 | assert(base); | ||
| 1431 | } | ||
| 1432 | |||
| 1433 | /* If we added a dict, DECREF it, or free inline values. */ | ||
| 1434 |
2/2✓ Branch 0 taken 81885713 times.
✓ Branch 1 taken 122121358 times.
|
204007071 | if (type->tp_flags & Py_TPFLAGS_MANAGED_DICT) { |
| 1435 | 81885713 | PyObject **dictptr = _PyObject_ManagedDictPointer(self); | |
| 1436 |
2/2✓ Branch 0 taken 3006082 times.
✓ Branch 1 taken 78879631 times.
|
81885713 | if (*dictptr != NULL) { |
| 1437 | assert(*_PyObject_ValuesPointer(self) == NULL); | ||
| 1438 | 3006082 | Py_DECREF(*dictptr); | |
| 1439 | 3006082 | *dictptr = NULL; | |
| 1440 | } | ||
| 1441 | else { | ||
| 1442 | 78879631 | _PyObject_FreeInstanceAttributes(self); | |
| 1443 | } | ||
| 1444 | } | ||
| 1445 |
4/4✓ Branch 0 taken 8383802 times.
✓ Branch 1 taken 113737556 times.
✓ Branch 2 taken 799621 times.
✓ Branch 3 taken 7584181 times.
|
122121358 | else if (type->tp_dictoffset && !base->tp_dictoffset) { |
| 1446 | 799621 | PyObject **dictptr = _PyObject_DictPointer(self); | |
| 1447 |
1/2✓ Branch 0 taken 799621 times.
✗ Branch 1 not taken.
|
799621 | if (dictptr != NULL) { |
| 1448 | 799621 | PyObject *dict = *dictptr; | |
| 1449 |
2/2✓ Branch 0 taken 519113 times.
✓ Branch 1 taken 280508 times.
|
799621 | if (dict != NULL) { |
| 1450 | 519113 | Py_DECREF(dict); | |
| 1451 | 519113 | *dictptr = NULL; | |
| 1452 | } | ||
| 1453 | } | ||
| 1454 | } | ||
| 1455 | |||
| 1456 | /* Extract the type again; tp_del may have changed it */ | ||
| 1457 | 204007071 | type = Py_TYPE(self); | |
| 1458 | |||
| 1459 | /* Call the base tp_dealloc(); first retrack self if | ||
| 1460 | * basedealloc knows about gc. | ||
| 1461 | */ | ||
| 1462 |
2/2✓ Branch 1 taken 13578920 times.
✓ Branch 2 taken 190428151 times.
|
204007071 | if (_PyType_IS_GC(base)) { |
| 1463 | 13578920 | _PyObject_GC_TRACK(self); | |
| 1464 | } | ||
| 1465 | |||
| 1466 | // Don't read type memory after calling basedealloc() since basedealloc() | ||
| 1467 | // can deallocate the type and free its memory. | ||
| 1468 | 408014142 | int type_needs_decref = (type->tp_flags & Py_TPFLAGS_HEAPTYPE | |
| 1469 |
3/4✓ Branch 0 taken 204007071 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 203496553 times.
✓ Branch 3 taken 510518 times.
|
204007071 | && !(base->tp_flags & Py_TPFLAGS_HEAPTYPE)); |
| 1470 | |||
| 1471 | assert(basedealloc); | ||
| 1472 | 204007071 | basedealloc(self); | |
| 1473 | |||
| 1474 | /* Can't reference self beyond this point. It's possible tp_del switched | ||
| 1475 | our type from a HEAPTYPE to a non-HEAPTYPE, so be careful about | ||
| 1476 | reference counting. Only decref if the base type is not already a heap | ||
| 1477 | allocated type. Otherwise, basedealloc should have decref'd it already */ | ||
| 1478 |
2/2✓ Branch 0 taken 510518 times.
✓ Branch 1 taken 203496553 times.
|
204007071 | if (type_needs_decref) { |
| 1479 | 203496553 | Py_DECREF(type); | |
| 1480 | } | ||
| 1481 | |||
| 1482 | 510518 | endlabel: | |
| 1483 |
1/2✓ Branch 0 taken 204007071 times.
✗ Branch 1 not taken.
|
204007071 | Py_TRASHCAN_END |
| 1484 | |||
| 1485 | /* Explanation of the weirdness around the trashcan macros: | ||
| 1486 | |||
| 1487 | Q. What do the trashcan macros do? | ||
| 1488 | |||
| 1489 | A. Read the comment titled "Trashcan mechanism" in object.h. | ||
| 1490 | For one, this explains why there must be a call to GC-untrack | ||
| 1491 | before the trashcan begin macro. Without understanding the | ||
| 1492 | trashcan code, the answers to the following questions don't make | ||
| 1493 | sense. | ||
| 1494 | |||
| 1495 | Q. Why do we GC-untrack before the trashcan and then immediately | ||
| 1496 | GC-track again afterward? | ||
| 1497 | |||
| 1498 | A. In the case that the base class is GC-aware, the base class | ||
| 1499 | probably GC-untracks the object. If it does that using the | ||
| 1500 | UNTRACK macro, this will crash when the object is already | ||
| 1501 | untracked. Because we don't know what the base class does, the | ||
| 1502 | only safe thing is to make sure the object is tracked when we | ||
| 1503 | call the base class dealloc. But... The trashcan begin macro | ||
| 1504 | requires that the object is *untracked* before it is called. So | ||
| 1505 | the dance becomes: | ||
| 1506 | |||
| 1507 | GC untrack | ||
| 1508 | trashcan begin | ||
| 1509 | GC track | ||
| 1510 | |||
| 1511 | Q. Why did the last question say "immediately GC-track again"? | ||
| 1512 | It's nowhere near immediately. | ||
| 1513 | |||
| 1514 | A. Because the code *used* to re-track immediately. Bad Idea. | ||
| 1515 | self has a refcount of 0, and if gc ever gets its hands on it | ||
| 1516 | (which can happen if any weakref callback gets invoked), it | ||
| 1517 | looks like trash to gc too, and gc also tries to delete self | ||
| 1518 | then. But we're already deleting self. Double deallocation is | ||
| 1519 | a subtle disaster. | ||
| 1520 | */ | ||
| 1521 | } | ||
| 1522 | |||
| 1523 | static PyTypeObject *solid_base(PyTypeObject *type); | ||
| 1524 | |||
| 1525 | /* type test with subclassing support */ | ||
| 1526 | |||
| 1527 | static int | ||
| 1528 | 5204710 | type_is_subtype_base_chain(PyTypeObject *a, PyTypeObject *b) | |
| 1529 | { | ||
| 1530 | do { | ||
| 1531 |
2/2✓ Branch 0 taken 1101926 times.
✓ Branch 1 taken 4102784 times.
|
5204710 | if (a == b) |
| 1532 | 1101926 | return 1; | |
| 1533 | 4102784 | a = a->tp_base; | |
| 1534 |
2/2✓ Branch 0 taken 4098129 times.
✓ Branch 1 taken 4655 times.
|
4102784 | } while (a != NULL); |
| 1535 | |||
| 1536 | 4655 | return (b == &PyBaseObject_Type); | |
| 1537 | } | ||
| 1538 | |||
| 1539 | int | ||
| 1540 | 1915173302 | PyType_IsSubtype(PyTypeObject *a, PyTypeObject *b) | |
| 1541 | { | ||
| 1542 | PyObject *mro; | ||
| 1543 | |||
| 1544 | 1915173302 | mro = a->tp_mro; | |
| 1545 |
2/2✓ Branch 0 taken 1914071376 times.
✓ Branch 1 taken 1101926 times.
|
1915173302 | if (mro != NULL) { |
| 1546 | /* Deal with multiple inheritance without recursion | ||
| 1547 | by walking the MRO tuple */ | ||
| 1548 | Py_ssize_t i, n; | ||
| 1549 | assert(PyTuple_Check(mro)); | ||
| 1550 | 1914071376 | n = PyTuple_GET_SIZE(mro); | |
| 1551 |
2/2✓ Branch 0 taken 4999712545 times.
✓ Branch 1 taken 1040929923 times.
|
6040642468 | for (i = 0; i < n; i++) { |
| 1552 |
2/2✓ Branch 0 taken 873141453 times.
✓ Branch 1 taken 4126571092 times.
|
4999712545 | if (PyTuple_GET_ITEM(mro, i) == (PyObject *)b) |
| 1553 | 873141453 | return 1; | |
| 1554 | } | ||
| 1555 | 1040929923 | return 0; | |
| 1556 | } | ||
| 1557 | else | ||
| 1558 | /* a is not completely initialized yet; follow tp_base */ | ||
| 1559 | 1101926 | return type_is_subtype_base_chain(a, b); | |
| 1560 | } | ||
| 1561 | |||
| 1562 | /* Routines to do a method lookup in the type without looking in the | ||
| 1563 | instance dictionary (so we can't use PyObject_GetAttr) but still | ||
| 1564 | binding it to the instance. | ||
| 1565 | |||
| 1566 | Variants: | ||
| 1567 | |||
| 1568 | - _PyObject_LookupSpecial() returns NULL without raising an exception | ||
| 1569 | when the _PyType_Lookup() call fails; | ||
| 1570 | |||
| 1571 | - lookup_maybe_method() and lookup_method() are internal routines similar | ||
| 1572 | to _PyObject_LookupSpecial(), but can return unbound PyFunction | ||
| 1573 | to avoid temporary method object. Pass self as first argument when | ||
| 1574 | unbound == 1. | ||
| 1575 | */ | ||
| 1576 | |||
| 1577 | PyObject * | ||
| 1578 | 102385927 | _PyObject_LookupSpecial(PyObject *self, PyObject *attr) | |
| 1579 | { | ||
| 1580 | PyObject *res; | ||
| 1581 | |||
| 1582 | 102385927 | res = _PyType_Lookup(Py_TYPE(self), attr); | |
| 1583 |
2/2✓ Branch 0 taken 72583626 times.
✓ Branch 1 taken 29802301 times.
|
102385927 | if (res != NULL) { |
| 1584 | descrgetfunc f; | ||
| 1585 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 72583626 times.
|
72583626 | if ((f = Py_TYPE(res)->tp_descr_get) == NULL) |
| 1586 | ✗ | Py_INCREF(res); | |
| 1587 | else | ||
| 1588 | 72583626 | res = f(res, self, (PyObject *)(Py_TYPE(self))); | |
| 1589 | } | ||
| 1590 | 102385927 | return res; | |
| 1591 | } | ||
| 1592 | |||
| 1593 | PyObject * | ||
| 1594 | ✗ | _PyObject_LookupSpecialId(PyObject *self, _Py_Identifier *attrid) | |
| 1595 | { | ||
| 1596 | ✗ | PyObject *attr = _PyUnicode_FromId(attrid); /* borrowed */ | |
| 1597 | ✗ | if (attr == NULL) | |
| 1598 | ✗ | return NULL; | |
| 1599 | ✗ | return _PyObject_LookupSpecial(self, attr); | |
| 1600 | } | ||
| 1601 | |||
| 1602 | static PyObject * | ||
| 1603 | 494080662 | lookup_maybe_method(PyObject *self, PyObject *attr, int *unbound) | |
| 1604 | { | ||
| 1605 | 494080662 | PyObject *res = _PyType_Lookup(Py_TYPE(self), attr); | |
| 1606 |
2/2✓ Branch 0 taken 44 times.
✓ Branch 1 taken 494080618 times.
|
494080662 | if (res == NULL) { |
| 1607 | 44 | return NULL; | |
| 1608 | } | ||
| 1609 | |||
| 1610 |
2/2✓ Branch 2 taken 476683698 times.
✓ Branch 3 taken 17396920 times.
|
494080618 | if (_PyType_HasFeature(Py_TYPE(res), Py_TPFLAGS_METHOD_DESCRIPTOR)) { |
| 1611 | /* Avoid temporary PyMethodObject */ | ||
| 1612 | 476683698 | *unbound = 1; | |
| 1613 | 476683698 | Py_INCREF(res); | |
| 1614 | } | ||
| 1615 | else { | ||
| 1616 | 17396920 | *unbound = 0; | |
| 1617 | 17396920 | descrgetfunc f = Py_TYPE(res)->tp_descr_get; | |
| 1618 |
2/2✓ Branch 0 taken 17149440 times.
✓ Branch 1 taken 247480 times.
|
17396920 | if (f == NULL) { |
| 1619 | 17149440 | Py_INCREF(res); | |
| 1620 | } | ||
| 1621 | else { | ||
| 1622 | 247480 | res = f(res, self, (PyObject *)(Py_TYPE(self))); | |
| 1623 | } | ||
| 1624 | } | ||
| 1625 | 494080618 | return res; | |
| 1626 | } | ||
| 1627 | |||
| 1628 | static PyObject * | ||
| 1629 | 232644792 | lookup_method(PyObject *self, PyObject *attr, int *unbound) | |
| 1630 | { | ||
| 1631 | 232644792 | PyObject *res = lookup_maybe_method(self, attr, unbound); | |
| 1632 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 232644792 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
|
232644792 | if (res == NULL && !PyErr_Occurred()) { |
| 1633 | ✗ | PyErr_SetObject(PyExc_AttributeError, attr); | |
| 1634 | } | ||
| 1635 | 232644792 | return res; | |
| 1636 | } | ||
| 1637 | |||
| 1638 | |||
| 1639 | static inline PyObject* | ||
| 1640 | 297808575 | vectorcall_unbound(PyThreadState *tstate, int unbound, PyObject *func, | |
| 1641 | PyObject *const *args, Py_ssize_t nargs) | ||
| 1642 | { | ||
| 1643 | 297808575 | size_t nargsf = nargs; | |
| 1644 |
2/2✓ Branch 0 taken 17382033 times.
✓ Branch 1 taken 280426542 times.
|
297808575 | if (!unbound) { |
| 1645 | /* Skip self argument, freeing up args[0] to use for | ||
| 1646 | * PY_VECTORCALL_ARGUMENTS_OFFSET */ | ||
| 1647 | 17382033 | args++; | |
| 1648 | 17382033 | nargsf = nargsf - 1 + PY_VECTORCALL_ARGUMENTS_OFFSET; | |
| 1649 | } | ||
| 1650 | EVAL_CALL_STAT_INC_IF_FUNCTION(EVAL_CALL_SLOT, func); | ||
| 1651 | 297808575 | return _PyObject_VectorcallTstate(tstate, func, args, nargsf, NULL); | |
| 1652 | } | ||
| 1653 | |||
| 1654 | static PyObject* | ||
| 1655 | 44235825 | call_unbound_noarg(int unbound, PyObject *func, PyObject *self) | |
| 1656 | { | ||
| 1657 |
1/2✓ Branch 0 taken 44235825 times.
✗ Branch 1 not taken.
|
44235825 | if (unbound) { |
| 1658 | 44235825 | return PyObject_CallOneArg(func, self); | |
| 1659 | } | ||
| 1660 | else { | ||
| 1661 | ✗ | return _PyObject_CallNoArgs(func); | |
| 1662 | } | ||
| 1663 | } | ||
| 1664 | |||
| 1665 | /* A variation of PyObject_CallMethod* that uses lookup_method() | ||
| 1666 | instead of PyObject_GetAttrString(). | ||
| 1667 | |||
| 1668 | args is an argument vector of length nargs. The first element in this | ||
| 1669 | vector is the special object "self" which is used for the method lookup */ | ||
| 1670 | static PyObject * | ||
| 1671 | 81722999 | vectorcall_method(PyObject *name, PyObject *const *args, Py_ssize_t nargs) | |
| 1672 | { | ||
| 1673 | assert(nargs >= 1); | ||
| 1674 | |||
| 1675 | 81722999 | PyThreadState *tstate = _PyThreadState_GET(); | |
| 1676 | int unbound; | ||
| 1677 | 81722999 | PyObject *self = args[0]; | |
| 1678 | 81722999 | PyObject *func = lookup_method(self, name, &unbound); | |
| 1679 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 81722999 times.
|
81722999 | if (func == NULL) { |
| 1680 | ✗ | return NULL; | |
| 1681 | } | ||
| 1682 | 81722999 | PyObject *retval = vectorcall_unbound(tstate, unbound, func, args, nargs); | |
| 1683 | 81722999 | Py_DECREF(func); | |
| 1684 | 81722999 | return retval; | |
| 1685 | } | ||
| 1686 | |||
| 1687 | /* Clone of vectorcall_method() that returns NotImplemented | ||
| 1688 | * when the lookup fails. */ | ||
| 1689 | static PyObject * | ||
| 1690 | 63274099 | vectorcall_maybe(PyThreadState *tstate, PyObject *name, | |
| 1691 | PyObject *const *args, Py_ssize_t nargs) | ||
| 1692 | { | ||
| 1693 | assert(nargs >= 1); | ||
| 1694 | |||
| 1695 | int unbound; | ||
| 1696 | 63274099 | PyObject *self = args[0]; | |
| 1697 | 63274099 | PyObject *func = lookup_maybe_method(self, name, &unbound); | |
| 1698 |
2/2✓ Branch 0 taken 44 times.
✓ Branch 1 taken 63274055 times.
|
63274099 | if (func == NULL) { |
| 1699 |
1/2✓ Branch 1 taken 44 times.
✗ Branch 2 not taken.
|
44 | if (!PyErr_Occurred()) |
| 1700 | 44 | Py_RETURN_NOTIMPLEMENTED; | |
| 1701 | ✗ | return NULL; | |
| 1702 | } | ||
| 1703 | 63274055 | PyObject *retval = vectorcall_unbound(tstate, unbound, func, args, nargs); | |
| 1704 | 63274055 | Py_DECREF(func); | |
| 1705 | 63274055 | return retval; | |
| 1706 | } | ||
| 1707 | |||
| 1708 | /* | ||
| 1709 | Method resolution order algorithm C3 described in | ||
| 1710 | "A Monotonic Superclass Linearization for Dylan", | ||
| 1711 | by Kim Barrett, Bob Cassel, Paul Haahr, | ||
| 1712 | David A. Moon, Keith Playford, and P. Tucker Withington. | ||
| 1713 | (OOPSLA 1996) | ||
| 1714 | |||
| 1715 | Some notes about the rules implied by C3: | ||
| 1716 | |||
| 1717 | No duplicate bases. | ||
| 1718 | It isn't legal to repeat a class in a list of base classes. | ||
| 1719 | |||
| 1720 | The next three properties are the 3 constraints in "C3". | ||
| 1721 | |||
| 1722 | Local precedence order. | ||
| 1723 | If A precedes B in C's MRO, then A will precede B in the MRO of all | ||
| 1724 | subclasses of C. | ||
| 1725 | |||
| 1726 | Monotonicity. | ||
| 1727 | The MRO of a class must be an extension without reordering of the | ||
| 1728 | MRO of each of its superclasses. | ||
| 1729 | |||
| 1730 | Extended Precedence Graph (EPG). | ||
| 1731 | Linearization is consistent if there is a path in the EPG from | ||
| 1732 | each class to all its successors in the linearization. See | ||
| 1733 | the paper for definition of EPG. | ||
| 1734 | */ | ||
| 1735 | |||
| 1736 | static int | ||
| 1737 | 14941620 | tail_contains(PyObject *tuple, int whence, PyObject *o) | |
| 1738 | { | ||
| 1739 | Py_ssize_t j, size; | ||
| 1740 | 14941620 | size = PyTuple_GET_SIZE(tuple); | |
| 1741 | |||
| 1742 |
2/2✓ Branch 0 taken 28665589 times.
✓ Branch 1 taken 14088125 times.
|
42753714 | for (j = whence+1; j < size; j++) { |
| 1743 |
2/2✓ Branch 0 taken 853495 times.
✓ Branch 1 taken 27812094 times.
|
28665589 | if (PyTuple_GET_ITEM(tuple, j) == o) |
| 1744 | 853495 | return 1; | |
| 1745 | } | ||
| 1746 | 14088125 | return 0; | |
| 1747 | } | ||
| 1748 | |||
| 1749 | static PyObject * | ||
| 1750 | ✗ | class_name(PyObject *cls) | |
| 1751 | { | ||
| 1752 | PyObject *name; | ||
| 1753 | ✗ | if (_PyObject_LookupAttr(cls, &_Py_ID(__name__), &name) == 0) { | |
| 1754 | ✗ | name = PyObject_Repr(cls); | |
| 1755 | } | ||
| 1756 | ✗ | return name; | |
| 1757 | } | ||
| 1758 | |||
| 1759 | static int | ||
| 1760 | 614962 | check_duplicates(PyObject *tuple) | |
| 1761 | { | ||
| 1762 | Py_ssize_t i, j, n; | ||
| 1763 | /* Let's use a quadratic time algorithm, | ||
| 1764 | assuming that the bases tuples is short. | ||
| 1765 | */ | ||
| 1766 | 614962 | n = PyTuple_GET_SIZE(tuple); | |
| 1767 |
2/2✓ Branch 0 taken 1247897 times.
✓ Branch 1 taken 614962 times.
|
1862859 | for (i = 0; i < n; i++) { |
| 1768 | 1247897 | PyObject *o = PyTuple_GET_ITEM(tuple, i); | |
| 1769 |
2/2✓ Branch 0 taken 676951 times.
✓ Branch 1 taken 1247897 times.
|
1924848 | for (j = i + 1; j < n; j++) { |
| 1770 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 676951 times.
|
676951 | if (PyTuple_GET_ITEM(tuple, j) == o) { |
| 1771 | ✗ | o = class_name(o); | |
| 1772 | ✗ | if (o != NULL) { | |
| 1773 | ✗ | if (PyUnicode_Check(o)) { | |
| 1774 | ✗ | PyErr_Format(PyExc_TypeError, | |
| 1775 | "duplicate base class %U", o); | ||
| 1776 | } | ||
| 1777 | else { | ||
| 1778 | ✗ | PyErr_SetString(PyExc_TypeError, | |
| 1779 | "duplicate base class"); | ||
| 1780 | } | ||
| 1781 | ✗ | Py_DECREF(o); | |
| 1782 | } | ||
| 1783 | ✗ | return -1; | |
| 1784 | } | ||
| 1785 | } | ||
| 1786 | } | ||
| 1787 | 614962 | return 0; | |
| 1788 | } | ||
| 1789 | |||
| 1790 | /* Raise a TypeError for an MRO order disagreement. | ||
| 1791 | |||
| 1792 | It's hard to produce a good error message. In the absence of better | ||
| 1793 | insight into error reporting, report the classes that were candidates | ||
| 1794 | to be put next into the MRO. There is some conflict between the | ||
| 1795 | order in which they should be put in the MRO, but it's hard to | ||
| 1796 | diagnose what constraint can't be satisfied. | ||
| 1797 | */ | ||
| 1798 | |||
| 1799 | static void | ||
| 1800 | ✗ | set_mro_error(PyObject **to_merge, Py_ssize_t to_merge_size, int *remain) | |
| 1801 | { | ||
| 1802 | Py_ssize_t i, n, off; | ||
| 1803 | char buf[1000]; | ||
| 1804 | PyObject *k, *v; | ||
| 1805 | ✗ | PyObject *set = PyDict_New(); | |
| 1806 | ✗ | if (!set) return; | |
| 1807 | |||
| 1808 | ✗ | for (i = 0; i < to_merge_size; i++) { | |
| 1809 | ✗ | PyObject *L = to_merge[i]; | |
| 1810 | ✗ | if (remain[i] < PyTuple_GET_SIZE(L)) { | |
| 1811 | ✗ | PyObject *c = PyTuple_GET_ITEM(L, remain[i]); | |
| 1812 | ✗ | if (PyDict_SetItem(set, c, Py_None) < 0) { | |
| 1813 | ✗ | Py_DECREF(set); | |
| 1814 | ✗ | return; | |
| 1815 | } | ||
| 1816 | } | ||
| 1817 | } | ||
| 1818 | ✗ | n = PyDict_GET_SIZE(set); | |
| 1819 | |||
| 1820 | ✗ | off = PyOS_snprintf(buf, sizeof(buf), "Cannot create a \ | |
| 1821 | consistent method resolution\norder (MRO) for bases"); | ||
| 1822 | ✗ | i = 0; | |
| 1823 | ✗ | while (PyDict_Next(set, &i, &k, &v) && (size_t)off < sizeof(buf)) { | |
| 1824 | ✗ | PyObject *name = class_name(k); | |
| 1825 | ✗ | const char *name_str = NULL; | |
| 1826 | ✗ | if (name != NULL) { | |
| 1827 | ✗ | if (PyUnicode_Check(name)) { | |
| 1828 | ✗ | name_str = PyUnicode_AsUTF8(name); | |
| 1829 | } | ||
| 1830 | else { | ||
| 1831 | ✗ | name_str = "?"; | |
| 1832 | } | ||
| 1833 | } | ||
| 1834 | ✗ | if (name_str == NULL) { | |
| 1835 | ✗ | Py_XDECREF(name); | |
| 1836 | ✗ | Py_DECREF(set); | |
| 1837 | ✗ | return; | |
| 1838 | } | ||
| 1839 | ✗ | off += PyOS_snprintf(buf + off, sizeof(buf) - off, " %s", name_str); | |
| 1840 | ✗ | Py_XDECREF(name); | |
| 1841 | ✗ | if (--n && (size_t)(off+1) < sizeof(buf)) { | |
| 1842 | ✗ | buf[off++] = ','; | |
| 1843 | ✗ | buf[off] = '\0'; | |
| 1844 | } | ||
| 1845 | } | ||
| 1846 | ✗ | PyErr_SetString(PyExc_TypeError, buf); | |
| 1847 | ✗ | Py_DECREF(set); | |
| 1848 | } | ||
| 1849 | |||
| 1850 | static int | ||
| 1851 | 614962 | pmerge(PyObject *acc, PyObject **to_merge, Py_ssize_t to_merge_size) | |
| 1852 | { | ||
| 1853 | 614962 | int res = 0; | |
| 1854 | Py_ssize_t i, j, empty_cnt; | ||
| 1855 | int *remain; | ||
| 1856 | |||
| 1857 | /* remain stores an index into each sublist of to_merge. | ||
| 1858 | remain[i] is the index of the next base in to_merge[i] | ||
| 1859 | that is not included in acc. | ||
| 1860 | */ | ||
| 1861 |
1/2✓ Branch 0 taken 614962 times.
✗ Branch 1 not taken.
|
614962 | remain = PyMem_New(int, to_merge_size); |
| 1862 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 614962 times.
|
614962 | if (remain == NULL) { |
| 1863 | ✗ | PyErr_NoMemory(); | |
| 1864 | ✗ | return -1; | |
| 1865 | } | ||
| 1866 |
2/2✓ Branch 0 taken 1862859 times.
✓ Branch 1 taken 614962 times.
|
2477821 | for (i = 0; i < to_merge_size; i++) |
| 1867 | 1862859 | remain[i] = 0; | |
| 1868 | |||
| 1869 | 614962 | again: | |
| 1870 | 4852217 | empty_cnt = 0; | |
| 1871 |
2/2✓ Branch 0 taken 6953609 times.
✓ Branch 1 taken 614962 times.
|
7568571 | for (i = 0; i < to_merge_size; i++) { |
| 1872 | PyObject *candidate; | ||
| 1873 | |||
| 1874 | 6953609 | PyObject *cur_tuple = to_merge[i]; | |
| 1875 | |||
| 1876 |
2/2✓ Branch 1 taken 1862859 times.
✓ Branch 2 taken 5090750 times.
|
6953609 | if (remain[i] >= PyTuple_GET_SIZE(cur_tuple)) { |
| 1877 | 1862859 | empty_cnt++; | |
| 1878 | 1862859 | continue; | |
| 1879 | } | ||
| 1880 | |||
| 1881 | /* Choose next candidate for MRO. | ||
| 1882 | |||
| 1883 | The input sequences alone can determine the choice. | ||
| 1884 | If not, choose the class which appears in the MRO | ||
| 1885 | of the earliest direct superclass of the new class. | ||
| 1886 | */ | ||
| 1887 | |||
| 1888 | 5090750 | candidate = PyTuple_GET_ITEM(cur_tuple, remain[i]); | |
| 1889 |
2/2✓ Branch 0 taken 14941620 times.
✓ Branch 1 taken 4237255 times.
|
19178875 | for (j = 0; j < to_merge_size; j++) { |
| 1890 | 14941620 | PyObject *j_lst = to_merge[j]; | |
| 1891 |
2/2✓ Branch 1 taken 853495 times.
✓ Branch 2 taken 14088125 times.
|
14941620 | if (tail_contains(j_lst, remain[j], candidate)) |
| 1892 | 853495 | goto skip; /* continue outer loop */ | |
| 1893 | } | ||
| 1894 | 4237255 | res = PyList_Append(acc, candidate); | |
| 1895 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4237255 times.
|
4237255 | if (res < 0) |
| 1896 | ✗ | goto out; | |
| 1897 | |||
| 1898 |
2/2✓ Branch 0 taken 12922381 times.
✓ Branch 1 taken 4237255 times.
|
17159636 | for (j = 0; j < to_merge_size; j++) { |
| 1899 | 12922381 | PyObject *j_lst = to_merge[j]; | |
| 1900 |
2/2✓ Branch 1 taken 10490681 times.
✓ Branch 2 taken 2431700 times.
|
12922381 | if (remain[j] < PyTuple_GET_SIZE(j_lst) && |
| 1901 |
2/2✓ Branch 0 taken 7347844 times.
✓ Branch 1 taken 3142837 times.
|
10490681 | PyTuple_GET_ITEM(j_lst, remain[j]) == candidate) { |
| 1902 | 7347844 | remain[j]++; | |
| 1903 | } | ||
| 1904 | } | ||
| 1905 | 4237255 | goto again; | |
| 1906 | 853495 | skip: ; | |
| 1907 | } | ||
| 1908 | |||
| 1909 |
1/2✓ Branch 0 taken 614962 times.
✗ Branch 1 not taken.
|
614962 | if (empty_cnt != to_merge_size) { |
| 1910 | ✗ | set_mro_error(to_merge, to_merge_size, remain); | |
| 1911 | ✗ | res = -1; | |
| 1912 | } | ||
| 1913 | |||
| 1914 | 614962 | out: | |
| 1915 | 614962 | PyMem_Free(remain); | |
| 1916 | |||
| 1917 | 614962 | return res; | |
| 1918 | } | ||
| 1919 | |||
| 1920 | static PyObject * | ||
| 1921 | 5158395 | mro_implementation(PyTypeObject *type) | |
| 1922 | { | ||
| 1923 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5158395 times.
|
5158395 | if (!_PyType_IsReady(type)) { |
| 1924 | ✗ | if (PyType_Ready(type) < 0) | |
| 1925 | ✗ | return NULL; | |
| 1926 | } | ||
| 1927 | |||
| 1928 | 5158395 | PyObject *bases = type->tp_bases; | |
| 1929 | 5158395 | Py_ssize_t n = PyTuple_GET_SIZE(bases); | |
| 1930 |
2/2✓ Branch 0 taken 5791330 times.
✓ Branch 1 taken 5158395 times.
|
10949725 | for (Py_ssize_t i = 0; i < n; i++) { |
| 1931 | 5791330 | PyTypeObject *base = _PyType_CAST(PyTuple_GET_ITEM(bases, i)); | |
| 1932 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5791330 times.
|
5791330 | if (base->tp_mro == NULL) { |
| 1933 | ✗ | PyErr_Format(PyExc_TypeError, | |
| 1934 | "Cannot extend an incomplete type '%.100s'", | ||
| 1935 | base->tp_name); | ||
| 1936 | ✗ | return NULL; | |
| 1937 | } | ||
| 1938 | assert(PyTuple_Check(base->tp_mro)); | ||
| 1939 | } | ||
| 1940 | |||
| 1941 |
2/2✓ Branch 0 taken 4543433 times.
✓ Branch 1 taken 614962 times.
|
5158395 | if (n == 1) { |
| 1942 | /* Fast path: if there is a single base, constructing the MRO | ||
| 1943 | * is trivial. | ||
| 1944 | */ | ||
| 1945 | 4543433 | PyTypeObject *base = _PyType_CAST(PyTuple_GET_ITEM(bases, 0)); | |
| 1946 | 4543433 | Py_ssize_t k = PyTuple_GET_SIZE(base->tp_mro); | |
| 1947 | 4543433 | PyObject *result = PyTuple_New(k + 1); | |
| 1948 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4543433 times.
|
4543433 | if (result == NULL) { |
| 1949 | ✗ | return NULL; | |
| 1950 | } | ||
| 1951 | |||
| 1952 | 4543433 | Py_INCREF(type); | |
| 1953 | 4543433 | PyTuple_SET_ITEM(result, 0, (PyObject *) type); | |
| 1954 |
2/2✓ Branch 0 taken 19452697 times.
✓ Branch 1 taken 4543433 times.
|
23996130 | for (Py_ssize_t i = 0; i < k; i++) { |
| 1955 | 19452697 | PyObject *cls = PyTuple_GET_ITEM(base->tp_mro, i); | |
| 1956 | 19452697 | Py_INCREF(cls); | |
| 1957 | 19452697 | PyTuple_SET_ITEM(result, i + 1, cls); | |
| 1958 | } | ||
| 1959 | 4543433 | return result; | |
| 1960 | } | ||
| 1961 | |||
| 1962 | /* This is just a basic sanity check. */ | ||
| 1963 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 614962 times.
|
614962 | if (check_duplicates(bases) < 0) { |
| 1964 | ✗ | return NULL; | |
| 1965 | } | ||
| 1966 | |||
| 1967 | /* Find a superclass linearization that honors the constraints | ||
| 1968 | of the explicit tuples of bases and the constraints implied by | ||
| 1969 | each base class. | ||
| 1970 | |||
| 1971 | to_merge is an array of tuples, where each tuple is a superclass | ||
| 1972 | linearization implied by a base class. The last element of | ||
| 1973 | to_merge is the declared tuple of bases. | ||
| 1974 | */ | ||
| 1975 |
1/2✓ Branch 0 taken 614962 times.
✗ Branch 1 not taken.
|
614962 | PyObject **to_merge = PyMem_New(PyObject *, n + 1); |
| 1976 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 614962 times.
|
614962 | if (to_merge == NULL) { |
| 1977 | ✗ | PyErr_NoMemory(); | |
| 1978 | ✗ | return NULL; | |
| 1979 | } | ||
| 1980 | |||
| 1981 |
2/2✓ Branch 0 taken 1247897 times.
✓ Branch 1 taken 614962 times.
|
1862859 | for (Py_ssize_t i = 0; i < n; i++) { |
| 1982 | 1247897 | PyTypeObject *base = _PyType_CAST(PyTuple_GET_ITEM(bases, i)); | |
| 1983 | 1247897 | to_merge[i] = base->tp_mro; | |
| 1984 | } | ||
| 1985 | 614962 | to_merge[n] = bases; | |
| 1986 | |||
| 1987 | 614962 | PyObject *result = PyList_New(1); | |
| 1988 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 614962 times.
|
614962 | if (result == NULL) { |
| 1989 | ✗ | PyMem_Free(to_merge); | |
| 1990 | ✗ | return NULL; | |
| 1991 | } | ||
| 1992 | |||
| 1993 | 614962 | Py_INCREF(type); | |
| 1994 | 614962 | PyList_SET_ITEM(result, 0, (PyObject *)type); | |
| 1995 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 614962 times.
|
614962 | if (pmerge(result, to_merge, n + 1) < 0) { |
| 1996 | ✗ | Py_CLEAR(result); | |
| 1997 | } | ||
| 1998 | 614962 | PyMem_Free(to_merge); | |
| 1999 | |||
| 2000 | 614962 | return result; | |
| 2001 | } | ||
| 2002 | |||
| 2003 | /*[clinic input] | ||
| 2004 | type.mro | ||
| 2005 | |||
| 2006 | Return a type's method resolution order. | ||
| 2007 | [clinic start generated code]*/ | ||
| 2008 | |||
| 2009 | static PyObject * | ||
| 2010 | 3040539 | type_mro_impl(PyTypeObject *self) | |
| 2011 | /*[clinic end generated code: output=bffc4a39b5b57027 input=28414f4e156db28d]*/ | ||
| 2012 | { | ||
| 2013 | PyObject *seq; | ||
| 2014 | 3040539 | seq = mro_implementation(self); | |
| 2015 |
3/4✓ Branch 0 taken 3040539 times.
✗ Branch 1 not taken.
✓ Branch 4 taken 2499388 times.
✓ Branch 5 taken 541151 times.
|
3040539 | if (seq != NULL && !PyList_Check(seq)) { |
| 2016 | 2499388 | Py_SETREF(seq, PySequence_List(seq)); | |
| 2017 | } | ||
| 2018 | 3040539 | return seq; | |
| 2019 | } | ||
| 2020 | |||
| 2021 | static int | ||
| 2022 | 371475 | mro_check(PyTypeObject *type, PyObject *mro) | |
| 2023 | { | ||
| 2024 | PyTypeObject *solid; | ||
| 2025 | Py_ssize_t i, n; | ||
| 2026 | |||
| 2027 | 371475 | solid = solid_base(type); | |
| 2028 | |||
| 2029 | 371475 | n = PyTuple_GET_SIZE(mro); | |
| 2030 |
2/2✓ Branch 0 taken 2240231 times.
✓ Branch 1 taken 371475 times.
|
2611706 | for (i = 0; i < n; i++) { |
| 2031 | 2240231 | PyObject *obj = PyTuple_GET_ITEM(mro, i); | |
| 2032 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 2240231 times.
|
2240231 | if (!PyType_Check(obj)) { |
| 2033 | ✗ | PyErr_Format( | |
| 2034 | PyExc_TypeError, | ||
| 2035 | "mro() returned a non-class ('%.500s')", | ||
| 2036 | ✗ | Py_TYPE(obj)->tp_name); | |
| 2037 | ✗ | return -1; | |
| 2038 | } | ||
| 2039 | 2240231 | PyTypeObject *base = (PyTypeObject*)obj; | |
| 2040 | |||
| 2041 |
1/2✗ Branch 2 not taken.
✓ Branch 3 taken 2240231 times.
|
2240231 | if (!PyType_IsSubtype(solid, solid_base(base))) { |
| 2042 | ✗ | PyErr_Format( | |
| 2043 | PyExc_TypeError, | ||
| 2044 | "mro() returned base with unsuitable layout ('%.500s')", | ||
| 2045 | base->tp_name); | ||
| 2046 | ✗ | return -1; | |
| 2047 | } | ||
| 2048 | } | ||
| 2049 | |||
| 2050 | 371475 | return 0; | |
| 2051 | } | ||
| 2052 | |||
| 2053 | /* Lookups an mcls.mro method, invokes it and checks the result (if needed, | ||
| 2054 | in case of a custom mro() implementation). | ||
| 2055 | |||
| 2056 | Keep in mind that during execution of this function type->tp_mro | ||
| 2057 | can be replaced due to possible reentrance (for example, | ||
| 2058 | through type_set_bases): | ||
| 2059 | |||
| 2060 | - when looking up the mcls.mro attribute (it could be | ||
| 2061 | a user-provided descriptor); | ||
| 2062 | |||
| 2063 | - from inside a custom mro() itself; | ||
| 2064 | |||
| 2065 | - through a finalizer of the return value of mro(). | ||
| 2066 | */ | ||
| 2067 | static PyObject * | ||
| 2068 | 2489331 | mro_invoke(PyTypeObject *type) | |
| 2069 | { | ||
| 2070 | PyObject *mro_result; | ||
| 2071 | PyObject *new_mro; | ||
| 2072 | 2489331 | const int custom = !Py_IS_TYPE(type, &PyType_Type); | |
| 2073 | |||
| 2074 |
2/2✓ Branch 0 taken 371475 times.
✓ Branch 1 taken 2117856 times.
|
2489331 | if (custom) { |
| 2075 | int unbound; | ||
| 2076 | 371475 | PyObject *mro_meth = lookup_method( | |
| 2077 | (PyObject *)type, &_Py_ID(mro), &unbound); | ||
| 2078 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 371475 times.
|
371475 | if (mro_meth == NULL) |
| 2079 | ✗ | return NULL; | |
| 2080 | 371475 | mro_result = call_unbound_noarg(unbound, mro_meth, (PyObject *)type); | |
| 2081 | 371475 | Py_DECREF(mro_meth); | |
| 2082 | } | ||
| 2083 | else { | ||
| 2084 | 2117856 | mro_result = mro_implementation(type); | |
| 2085 | } | ||
| 2086 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2489331 times.
|
2489331 | if (mro_result == NULL) |
| 2087 | ✗ | return NULL; | |
| 2088 | |||
| 2089 | 2489331 | new_mro = PySequence_Tuple(mro_result); | |
| 2090 | 2489331 | Py_DECREF(mro_result); | |
| 2091 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2489331 times.
|
2489331 | if (new_mro == NULL) { |
| 2092 | ✗ | return NULL; | |
| 2093 | } | ||
| 2094 | |||
| 2095 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 2489331 times.
|
2489331 | if (PyTuple_GET_SIZE(new_mro) == 0) { |
| 2096 | ✗ | Py_DECREF(new_mro); | |
| 2097 | ✗ | PyErr_Format(PyExc_TypeError, "type MRO must not be empty"); | |
| 2098 | ✗ | return NULL; | |
| 2099 | } | ||
| 2100 | |||
| 2101 |
3/4✓ Branch 0 taken 371475 times.
✓ Branch 1 taken 2117856 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 371475 times.
|
2489331 | if (custom && mro_check(type, new_mro) < 0) { |
| 2102 | ✗ | Py_DECREF(new_mro); | |
| 2103 | ✗ | return NULL; | |
| 2104 | } | ||
| 2105 | 2489331 | return new_mro; | |
| 2106 | } | ||
| 2107 | |||
| 2108 | /* Calculates and assigns a new MRO to type->tp_mro. | ||
| 2109 | Return values and invariants: | ||
| 2110 | |||
| 2111 | - Returns 1 if a new MRO value has been set to type->tp_mro due to | ||
| 2112 | this call of mro_internal (no tricky reentrancy and no errors). | ||
| 2113 | |||
| 2114 | In case if p_old_mro argument is not NULL, a previous value | ||
| 2115 | of type->tp_mro is put there, and the ownership of this | ||
| 2116 | reference is transferred to a caller. | ||
| 2117 | Otherwise, the previous value (if any) is decref'ed. | ||
| 2118 | |||
| 2119 | - Returns 0 in case when type->tp_mro gets changed because of | ||
| 2120 | reentering here through a custom mro() (see a comment to mro_invoke). | ||
| 2121 | |||
| 2122 | In this case, a refcount of an old type->tp_mro is adjusted | ||
| 2123 | somewhere deeper in the call stack (by the innermost mro_internal | ||
| 2124 | or its caller) and may become zero upon returning from here. | ||
| 2125 | This also implies that the whole hierarchy of subclasses of the type | ||
| 2126 | has seen the new value and updated their MRO accordingly. | ||
| 2127 | |||
| 2128 | - Returns -1 in case of an error. | ||
| 2129 | */ | ||
| 2130 | static int | ||
| 2131 | 2489331 | mro_internal(PyTypeObject *type, PyObject **p_old_mro) | |
| 2132 | { | ||
| 2133 | PyObject *new_mro, *old_mro; | ||
| 2134 | int reent; | ||
| 2135 | |||
| 2136 | /* Keep a reference to be able to do a reentrancy check below. | ||
| 2137 | Don't let old_mro be GC'ed and its address be reused for | ||
| 2138 | another object, like (suddenly!) a new tp_mro. */ | ||
| 2139 | 2489331 | old_mro = type->tp_mro; | |
| 2140 | 2489331 | Py_XINCREF(old_mro); | |
| 2141 | 2489331 | new_mro = mro_invoke(type); /* might cause reentrance */ | |
| 2142 | 2489331 | reent = (type->tp_mro != old_mro); | |
| 2143 | 2489331 | Py_XDECREF(old_mro); | |
| 2144 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2489331 times.
|
2489331 | if (new_mro == NULL) { |
| 2145 | ✗ | return -1; | |
| 2146 | } | ||
| 2147 | |||
| 2148 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2489331 times.
|
2489331 | if (reent) { |
| 2149 | ✗ | Py_DECREF(new_mro); | |
| 2150 | ✗ | return 0; | |
| 2151 | } | ||
| 2152 | |||
| 2153 | 2489331 | type->tp_mro = new_mro; | |
| 2154 | |||
| 2155 | 2489331 | type_mro_modified(type, type->tp_mro); | |
| 2156 | /* corner case: the super class might have been hidden | ||
| 2157 | from the custom MRO */ | ||
| 2158 | 2489331 | type_mro_modified(type, type->tp_bases); | |
| 2159 | |||
| 2160 | 2489331 | PyType_Modified(type); | |
| 2161 | |||
| 2162 |
2/2✓ Branch 0 taken 4655 times.
✓ Branch 1 taken 2484676 times.
|
2489331 | if (p_old_mro != NULL) |
| 2163 | 4655 | *p_old_mro = old_mro; /* transfer the ownership */ | |
| 2164 | else | ||
| 2165 | 2484676 | Py_XDECREF(old_mro); | |
| 2166 | |||
| 2167 | 2489331 | return 1; | |
| 2168 | } | ||
| 2169 | |||
| 2170 | /* Calculate the best base amongst multiple base classes. | ||
| 2171 | This is the first one that's on the path to the "solid base". */ | ||
| 2172 | |||
| 2173 | static PyTypeObject * | ||
| 2174 | 1378685 | best_base(PyObject *bases) | |
| 2175 | { | ||
| 2176 | Py_ssize_t i, n; | ||
| 2177 | PyTypeObject *base, *winner, *candidate; | ||
| 2178 | |||
| 2179 | assert(PyTuple_Check(bases)); | ||
| 2180 | 1378685 | n = PyTuple_GET_SIZE(bases); | |
| 2181 | assert(n > 0); | ||
| 2182 | 1378685 | base = NULL; | |
| 2183 | 1378685 | winner = NULL; | |
| 2184 |
2/2✓ Branch 0 taken 1532492 times.
✓ Branch 1 taken 1378685 times.
|
2911177 | for (i = 0; i < n; i++) { |
| 2185 | 1532492 | PyObject *base_proto = PyTuple_GET_ITEM(bases, i); | |
| 2186 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 1532492 times.
|
1532492 | if (!PyType_Check(base_proto)) { |
| 2187 | ✗ | PyErr_SetString( | |
| 2188 | PyExc_TypeError, | ||
| 2189 | "bases must be types"); | ||
| 2190 | ✗ | return NULL; | |
| 2191 | } | ||
| 2192 | 1532492 | PyTypeObject *base_i = (PyTypeObject *)base_proto; | |
| 2193 | |||
| 2194 |
2/2✓ Branch 0 taken 1819 times.
✓ Branch 1 taken 1530673 times.
|
1532492 | if (!_PyType_IsReady(base_i)) { |
| 2195 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 1819 times.
|
1819 | if (PyType_Ready(base_i) < 0) |
| 2196 | ✗ | return NULL; | |
| 2197 | } | ||
| 2198 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 1532492 times.
|
1532492 | if (!_PyType_HasFeature(base_i, Py_TPFLAGS_BASETYPE)) { |
| 2199 | ✗ | PyErr_Format(PyExc_TypeError, | |
| 2200 | "type '%.100s' is not an acceptable base type", | ||
| 2201 | base_i->tp_name); | ||
| 2202 | ✗ | return NULL; | |
| 2203 | } | ||
| 2204 | 1532492 | candidate = solid_base(base_i); | |
| 2205 |
2/2✓ Branch 0 taken 1378685 times.
✓ Branch 1 taken 153807 times.
|
1532492 | if (winner == NULL) { |
| 2206 | 1378685 | winner = candidate; | |
| 2207 | 1378685 | base = base_i; | |
| 2208 | } | ||
| 2209 |
2/2✓ Branch 1 taken 3782 times.
✓ Branch 2 taken 150025 times.
|
153807 | else if (PyType_IsSubtype(winner, candidate)) |
| 2210 | ; | ||
| 2211 |
1/2✓ Branch 1 taken 3782 times.
✗ Branch 2 not taken.
|
3782 | else if (PyType_IsSubtype(candidate, winner)) { |
| 2212 | 3782 | winner = candidate; | |
| 2213 | 3782 | base = base_i; | |
| 2214 | } | ||
| 2215 | else { | ||
| 2216 | ✗ | PyErr_SetString( | |
| 2217 | PyExc_TypeError, | ||
| 2218 | "multiple bases have " | ||
| 2219 | "instance lay-out conflict"); | ||
| 2220 | ✗ | return NULL; | |
| 2221 | } | ||
| 2222 | } | ||
| 2223 | assert (base != NULL); | ||
| 2224 | |||
| 2225 | 1378685 | return base; | |
| 2226 | } | ||
| 2227 | |||
| 2228 | static int | ||
| 2229 | 12139524 | extra_ivars(PyTypeObject *type, PyTypeObject *base) | |
| 2230 | { | ||
| 2231 | 12139524 | size_t t_size = type->tp_basicsize; | |
| 2232 | 12139524 | size_t b_size = base->tp_basicsize; | |
| 2233 | |||
| 2234 | assert(t_size >= b_size); /* Else type smaller than base! */ | ||
| 2235 |
3/4✓ Branch 0 taken 11578847 times.
✓ Branch 1 taken 560677 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 11578847 times.
|
12139524 | if (type->tp_itemsize || base->tp_itemsize) { |
| 2236 | /* If itemsize is involved, stricter rules */ | ||
| 2237 |
2/2✓ Branch 0 taken 79374 times.
✓ Branch 1 taken 481303 times.
|
640051 | return t_size != b_size || |
| 2238 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 79374 times.
|
79374 | type->tp_itemsize != base->tp_itemsize; |
| 2239 | } | ||
| 2240 |
4/4✓ Branch 0 taken 3333341 times.
✓ Branch 1 taken 8245506 times.
✓ Branch 2 taken 3115969 times.
✓ Branch 3 taken 217372 times.
|
11578847 | if (type->tp_weaklistoffset && base->tp_weaklistoffset == 0 && |
| 2241 |
2/2✓ Branch 0 taken 3105221 times.
✓ Branch 1 taken 10748 times.
|
3115969 | type->tp_weaklistoffset + sizeof(PyObject *) == t_size && |
| 2242 |
2/2✓ Branch 0 taken 2926553 times.
✓ Branch 1 taken 178668 times.
|
3105221 | type->tp_flags & Py_TPFLAGS_HEAPTYPE) |
| 2243 | 2926553 | t_size -= sizeof(PyObject *); | |
| 2244 | 11578847 | return t_size != b_size; | |
| 2245 | } | ||
| 2246 | |||
| 2247 | static PyTypeObject * | ||
| 2248 | 12139524 | solid_base(PyTypeObject *type) | |
| 2249 | { | ||
| 2250 | PyTypeObject *base; | ||
| 2251 | |||
| 2252 |
2/2✓ Branch 0 taken 7995326 times.
✓ Branch 1 taken 4144198 times.
|
12139524 | if (type->tp_base) |
| 2253 | 7995326 | base = solid_base(type->tp_base); | |
| 2254 | else | ||
| 2255 | 4144198 | base = &PyBaseObject_Type; | |
| 2256 |
2/2✓ Branch 1 taken 1877692 times.
✓ Branch 2 taken 10261832 times.
|
12139524 | if (extra_ivars(type, base)) |
| 2257 | 1877692 | return type; | |
| 2258 | else | ||
| 2259 | 10261832 | return base; | |
| 2260 | } | ||
| 2261 | |||
| 2262 | static void object_dealloc(PyObject *); | ||
| 2263 | static PyObject *object_new(PyTypeObject *, PyObject *, PyObject *); | ||
| 2264 | static int object_init(PyObject *, PyObject *, PyObject *); | ||
| 2265 | static int update_slot(PyTypeObject *, PyObject *); | ||
| 2266 | static void fixup_slot_dispatchers(PyTypeObject *); | ||
| 2267 | static int type_new_set_names(PyTypeObject *); | ||
| 2268 | static int type_new_init_subclass(PyTypeObject *, PyObject *); | ||
| 2269 | |||
| 2270 | /* | ||
| 2271 | * Helpers for __dict__ descriptor. We don't want to expose the dicts | ||
| 2272 | * inherited from various builtin types. The builtin base usually provides | ||
| 2273 | * its own __dict__ descriptor, so we use that when we can. | ||
| 2274 | */ | ||
| 2275 | static PyTypeObject * | ||
| 2276 | 2693794 | get_builtin_base_with_dict(PyTypeObject *type) | |
| 2277 | { | ||
| 2278 |
2/2✓ Branch 0 taken 6237249 times.
✓ Branch 1 taken 2693794 times.
|
8931043 | while (type->tp_base != NULL) { |
| 2279 |
2/2✓ Branch 0 taken 5870119 times.
✓ Branch 1 taken 367130 times.
|
6237249 | if (type->tp_dictoffset != 0 && |
| 2280 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5870119 times.
|
5870119 | !(type->tp_flags & Py_TPFLAGS_HEAPTYPE)) |
| 2281 | ✗ | return type; | |
| 2282 | 6237249 | type = type->tp_base; | |
| 2283 | } | ||
| 2284 | 2693794 | return NULL; | |
| 2285 | } | ||
| 2286 | |||
| 2287 | static PyObject * | ||
| 2288 | ✗ | get_dict_descriptor(PyTypeObject *type) | |
| 2289 | { | ||
| 2290 | PyObject *descr; | ||
| 2291 | |||
| 2292 | ✗ | descr = _PyType_Lookup(type, &_Py_ID(__dict__)); | |
| 2293 | ✗ | if (descr == NULL || !PyDescr_IsData(descr)) | |
| 2294 | ✗ | return NULL; | |
| 2295 | |||
| 2296 | ✗ | return descr; | |
| 2297 | } | ||
| 2298 | |||
| 2299 | static void | ||
| 2300 | ✗ | raise_dict_descr_error(PyObject *obj) | |
| 2301 | { | ||
| 2302 | ✗ | PyErr_Format(PyExc_TypeError, | |
| 2303 | "this __dict__ descriptor does not support " | ||
| 2304 | ✗ | "'%.200s' objects", Py_TYPE(obj)->tp_name); | |
| 2305 | } | ||
| 2306 | |||
| 2307 | static PyObject * | ||
| 2308 | 2650729 | subtype_dict(PyObject *obj, void *context) | |
| 2309 | { | ||
| 2310 | PyTypeObject *base; | ||
| 2311 | |||
| 2312 | 2650729 | base = get_builtin_base_with_dict(Py_TYPE(obj)); | |
| 2313 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2650729 times.
|
2650729 | if (base != NULL) { |
| 2314 | descrgetfunc func; | ||
| 2315 | ✗ | PyObject *descr = get_dict_descriptor(base); | |
| 2316 | ✗ | if (descr == NULL) { | |
| 2317 | ✗ | raise_dict_descr_error(obj); | |
| 2318 | ✗ | return NULL; | |
| 2319 | } | ||
| 2320 | ✗ | func = Py_TYPE(descr)->tp_descr_get; | |
| 2321 | ✗ | if (func == NULL) { | |
| 2322 | ✗ | raise_dict_descr_error(obj); | |
| 2323 | ✗ | return NULL; | |
| 2324 | } | ||
| 2325 | ✗ | return func(descr, obj, (PyObject *)(Py_TYPE(obj))); | |
| 2326 | } | ||
| 2327 | 2650729 | return PyObject_GenericGetDict(obj, context); | |
| 2328 | } | ||
| 2329 | |||
| 2330 | static int | ||
| 2331 | 43065 | subtype_setdict(PyObject *obj, PyObject *value, void *context) | |
| 2332 | { | ||
| 2333 | PyObject **dictptr; | ||
| 2334 | PyTypeObject *base; | ||
| 2335 | |||
| 2336 | 43065 | base = get_builtin_base_with_dict(Py_TYPE(obj)); | |
| 2337 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 43065 times.
|
43065 | if (base != NULL) { |
| 2338 | descrsetfunc func; | ||
| 2339 | ✗ | PyObject *descr = get_dict_descriptor(base); | |
| 2340 | ✗ | if (descr == NULL) { | |
| 2341 | ✗ | raise_dict_descr_error(obj); | |
| 2342 | ✗ | return -1; | |
| 2343 | } | ||
| 2344 | ✗ | func = Py_TYPE(descr)->tp_descr_set; | |
| 2345 | ✗ | if (func == NULL) { | |
| 2346 | ✗ | raise_dict_descr_error(obj); | |
| 2347 | ✗ | return -1; | |
| 2348 | } | ||
| 2349 | ✗ | return func(descr, obj, value); | |
| 2350 | } | ||
| 2351 | /* Almost like PyObject_GenericSetDict, but allow __dict__ to be deleted. */ | ||
| 2352 | 43065 | dictptr = _PyObject_GetDictPtr(obj); | |
| 2353 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 43065 times.
|
43065 | if (dictptr == NULL) { |
| 2354 | ✗ | PyErr_SetString(PyExc_AttributeError, | |
| 2355 | "This object has no __dict__"); | ||
| 2356 | ✗ | return -1; | |
| 2357 | } | ||
| 2358 |
2/4✓ Branch 0 taken 43065 times.
✗ Branch 1 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 43065 times.
|
43065 | if (value != NULL && !PyDict_Check(value)) { |
| 2359 | ✗ | PyErr_Format(PyExc_TypeError, | |
| 2360 | "__dict__ must be set to a dictionary, " | ||
| 2361 | ✗ | "not a '%.200s'", Py_TYPE(value)->tp_name); | |
| 2362 | ✗ | return -1; | |
| 2363 | } | ||
| 2364 | 43065 | Py_XINCREF(value); | |
| 2365 | 43065 | Py_XSETREF(*dictptr, value); | |
| 2366 | 43065 | return 0; | |
| 2367 | } | ||
| 2368 | |||
| 2369 | static PyObject * | ||
| 2370 | ✗ | subtype_getweakref(PyObject *obj, void *context) | |
| 2371 | { | ||
| 2372 | PyObject **weaklistptr; | ||
| 2373 | PyObject *result; | ||
| 2374 | ✗ | PyTypeObject *type = Py_TYPE(obj); | |
| 2375 | |||
| 2376 | ✗ | if (type->tp_weaklistoffset == 0) { | |
| 2377 | ✗ | PyErr_SetString(PyExc_AttributeError, | |
| 2378 | "This object has no __weakref__"); | ||
| 2379 | ✗ | return NULL; | |
| 2380 | } | ||
| 2381 | _PyObject_ASSERT((PyObject *)type, | ||
| 2382 | type->tp_weaklistoffset > 0); | ||
| 2383 | _PyObject_ASSERT((PyObject *)type, | ||
| 2384 | ((type->tp_weaklistoffset + sizeof(PyObject *)) | ||
| 2385 | <= (size_t)(type->tp_basicsize))); | ||
| 2386 | ✗ | weaklistptr = (PyObject **)((char *)obj + type->tp_weaklistoffset); | |
| 2387 | ✗ | if (*weaklistptr == NULL) | |
| 2388 | ✗ | result = Py_None; | |
| 2389 | else | ||
| 2390 | ✗ | result = *weaklistptr; | |
| 2391 | ✗ | Py_INCREF(result); | |
| 2392 | ✗ | return result; | |
| 2393 | } | ||
| 2394 | |||
| 2395 | /* Three variants on the subtype_getsets list. */ | ||
| 2396 | |||
| 2397 | static PyGetSetDef subtype_getsets_full[] = { | ||
| 2398 | {"__dict__", subtype_dict, subtype_setdict, | ||
| 2399 | PyDoc_STR("dictionary for instance variables (if defined)")}, | ||
| 2400 | {"__weakref__", subtype_getweakref, NULL, | ||
| 2401 | PyDoc_STR("list of weak references to the object (if defined)")}, | ||
| 2402 | {0} | ||
| 2403 | }; | ||
| 2404 | |||
| 2405 | static PyGetSetDef subtype_getsets_dict_only[] = { | ||
| 2406 | {"__dict__", subtype_dict, subtype_setdict, | ||
| 2407 | PyDoc_STR("dictionary for instance variables (if defined)")}, | ||
| 2408 | {0} | ||
| 2409 | }; | ||
| 2410 | |||
| 2411 | static PyGetSetDef subtype_getsets_weakref_only[] = { | ||
| 2412 | {"__weakref__", subtype_getweakref, NULL, | ||
| 2413 | PyDoc_STR("list of weak references to the object (if defined)")}, | ||
| 2414 | {0} | ||
| 2415 | }; | ||
| 2416 | |||
| 2417 | static int | ||
| 2418 | 251284 | valid_identifier(PyObject *s) | |
| 2419 | { | ||
| 2420 |
1/2✗ Branch 2 not taken.
✓ Branch 3 taken 251284 times.
|
251284 | if (!PyUnicode_Check(s)) { |
| 2421 | ✗ | PyErr_Format(PyExc_TypeError, | |
| 2422 | "__slots__ items must be strings, not '%.200s'", | ||
| 2423 | ✗ | Py_TYPE(s)->tp_name); | |
| 2424 | ✗ | return 0; | |
| 2425 | } | ||
| 2426 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 251284 times.
|
251284 | if (!PyUnicode_IsIdentifier(s)) { |
| 2427 | ✗ | PyErr_SetString(PyExc_TypeError, | |
| 2428 | "__slots__ must be identifiers"); | ||
| 2429 | ✗ | return 0; | |
| 2430 | } | ||
| 2431 | 251284 | return 1; | |
| 2432 | } | ||
| 2433 | |||
| 2434 | static int | ||
| 2435 | 1532762 | type_init(PyObject *cls, PyObject *args, PyObject *kwds) | |
| 2436 | { | ||
| 2437 | assert(args != NULL && PyTuple_Check(args)); | ||
| 2438 | assert(kwds == NULL || PyDict_Check(kwds)); | ||
| 2439 | |||
| 2440 |
3/6✓ Branch 0 taken 82653 times.
✓ Branch 1 taken 1450109 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 82653 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
|
1532762 | if (kwds != NULL && PyTuple_GET_SIZE(args) == 1 && |
| 2441 | ✗ | PyDict_GET_SIZE(kwds) != 0) { | |
| 2442 | ✗ | PyErr_SetString(PyExc_TypeError, | |
| 2443 | "type.__init__() takes no keyword arguments"); | ||
| 2444 | ✗ | return -1; | |
| 2445 | } | ||
| 2446 | |||
| 2447 |
2/4✓ Branch 1 taken 1532762 times.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1532762 times.
|
1532762 | if ((PyTuple_GET_SIZE(args) != 1 && PyTuple_GET_SIZE(args) != 3)) { |
| 2448 | ✗ | PyErr_SetString(PyExc_TypeError, | |
| 2449 | "type.__init__() takes 1 or 3 arguments"); | ||
| 2450 | ✗ | return -1; | |
| 2451 | } | ||
| 2452 | |||
| 2453 | 1532762 | return 0; | |
| 2454 | } | ||
| 2455 | |||
| 2456 | |||
| 2457 | unsigned long | ||
| 2458 | ✗ | PyType_GetFlags(PyTypeObject *type) | |
| 2459 | { | ||
| 2460 | ✗ | return type->tp_flags; | |
| 2461 | } | ||
| 2462 | |||
| 2463 | |||
| 2464 | int | ||
| 2465 | ✗ | PyType_SUPPORTS_WEAKREFS(PyTypeObject *type) | |
| 2466 | { | ||
| 2467 | ✗ | return _PyType_SUPPORTS_WEAKREFS(type); | |
| 2468 | } | ||
| 2469 | |||
| 2470 | |||
| 2471 | /* Determine the most derived metatype. */ | ||
| 2472 | PyTypeObject * | ||
| 2473 | 2686226 | _PyType_CalculateMetaclass(PyTypeObject *metatype, PyObject *bases) | |
| 2474 | { | ||
| 2475 | Py_ssize_t i, nbases; | ||
| 2476 | PyTypeObject *winner; | ||
| 2477 | PyObject *tmp; | ||
| 2478 | PyTypeObject *tmptype; | ||
| 2479 | |||
| 2480 | /* Determine the proper metatype to deal with this, | ||
| 2481 | and check for metatype conflicts while we're at it. | ||
| 2482 | Note that if some other metatype wins to contract, | ||
| 2483 | it's possible that its instances are not types. */ | ||
| 2484 | |||
| 2485 | 2686226 | nbases = PyTuple_GET_SIZE(bases); | |
| 2486 | 2686226 | winner = metatype; | |
| 2487 |
2/2✓ Branch 0 taken 2637581 times.
✓ Branch 1 taken 2686226 times.
|
5323807 | for (i = 0; i < nbases; i++) { |
| 2488 | 2637581 | tmp = PyTuple_GET_ITEM(bases, i); | |
| 2489 | 2637581 | tmptype = Py_TYPE(tmp); | |
| 2490 |
2/2✓ Branch 1 taken 2574680 times.
✓ Branch 2 taken 62901 times.
|
2637581 | if (PyType_IsSubtype(winner, tmptype)) |
| 2491 | 2574680 | continue; | |
| 2492 |
1/2✓ Branch 1 taken 62901 times.
✗ Branch 2 not taken.
|
62901 | if (PyType_IsSubtype(tmptype, winner)) { |
| 2493 | 62901 | winner = tmptype; | |
| 2494 | 62901 | continue; | |
| 2495 | } | ||
| 2496 | /* else: */ | ||
| 2497 | ✗ | PyErr_SetString(PyExc_TypeError, | |
| 2498 | "metaclass conflict: " | ||
| 2499 | "the metaclass of a derived class " | ||
| 2500 | "must be a (non-strict) subclass " | ||
| 2501 | "of the metaclasses of all its bases"); | ||
| 2502 | ✗ | return NULL; | |
| 2503 | } | ||
| 2504 | 2686226 | return winner; | |
| 2505 | } | ||
| 2506 | |||
| 2507 | |||
| 2508 | // Forward declaration | ||
| 2509 | static PyObject * | ||
| 2510 | type_new(PyTypeObject *metatype, PyObject *args, PyObject *kwds); | ||
| 2511 | |||
| 2512 | typedef struct { | ||
| 2513 | PyTypeObject *metatype; | ||
| 2514 | PyObject *args; | ||
| 2515 | PyObject *kwds; | ||
| 2516 | PyObject *orig_dict; | ||
| 2517 | PyObject *name; | ||
| 2518 | PyObject *bases; | ||
| 2519 | PyTypeObject *base; | ||
| 2520 | PyObject *slots; | ||
| 2521 | Py_ssize_t nslot; | ||
| 2522 | int add_dict; | ||
| 2523 | int add_weak; | ||
| 2524 | int may_add_dict; | ||
| 2525 | int may_add_weak; | ||
| 2526 | } type_new_ctx; | ||
| 2527 | |||
| 2528 | |||
| 2529 | /* Check for valid slot names and two special cases */ | ||
| 2530 | static int | ||
| 2531 | 279850 | type_new_visit_slots(type_new_ctx *ctx) | |
| 2532 | { | ||
| 2533 | 279850 | PyObject *slots = ctx->slots; | |
| 2534 | 279850 | Py_ssize_t nslot = ctx->nslot; | |
| 2535 |
2/2✓ Branch 0 taken 251284 times.
✓ Branch 1 taken 279850 times.
|
531134 | for (Py_ssize_t i = 0; i < nslot; i++) { |
| 2536 | 251284 | PyObject *name = PyTuple_GET_ITEM(slots, i); | |
| 2537 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 251284 times.
|
251284 | if (!valid_identifier(name)) { |
| 2538 | ✗ | return -1; | |
| 2539 | } | ||
| 2540 | assert(PyUnicode_Check(name)); | ||
| 2541 |
2/2✓ Branch 1 taken 2501 times.
✓ Branch 2 taken 248783 times.
|
251284 | if (_PyUnicode_Equal(name, &_Py_ID(__dict__))) { |
| 2542 |
2/4✓ Branch 0 taken 2501 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2501 times.
|
2501 | if (!ctx->may_add_dict || ctx->add_dict != 0) { |
| 2543 | ✗ | PyErr_SetString(PyExc_TypeError, | |
| 2544 | "__dict__ slot disallowed: " | ||
| 2545 | "we already got one"); | ||
| 2546 | ✗ | return -1; | |
| 2547 | } | ||
| 2548 | 2501 | ctx->add_dict++; | |
| 2549 | } | ||
| 2550 |
2/2✓ Branch 1 taken 10700 times.
✓ Branch 2 taken 240584 times.
|
251284 | if (_PyUnicode_Equal(name, &_Py_ID(__weakref__))) { |
| 2551 |
2/4✓ Branch 0 taken 10700 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 10700 times.
|
10700 | if (!ctx->may_add_weak || ctx->add_weak != 0) { |
| 2552 | ✗ | PyErr_SetString(PyExc_TypeError, | |
| 2553 | "__weakref__ slot disallowed: " | ||
| 2554 | "either we already got one, " | ||
| 2555 | "or __itemsize__ != 0"); | ||
| 2556 | ✗ | return -1; | |
| 2557 | } | ||
| 2558 | 10700 | ctx->add_weak++; | |
| 2559 | } | ||
| 2560 | } | ||
| 2561 | 279850 | return 0; | |
| 2562 | } | ||
| 2563 | |||
| 2564 | |||
| 2565 | /* Copy slots into a list, mangle names and sort them. | ||
| 2566 | Sorted names are needed for __class__ assignment. | ||
| 2567 | Convert them back to tuple at the end. | ||
| 2568 | */ | ||
| 2569 | static PyObject* | ||
| 2570 | 279850 | type_new_copy_slots(type_new_ctx *ctx, PyObject *dict) | |
| 2571 | { | ||
| 2572 | 279850 | PyObject *slots = ctx->slots; | |
| 2573 | 279850 | Py_ssize_t nslot = ctx->nslot; | |
| 2574 | |||
| 2575 | 279850 | Py_ssize_t new_nslot = nslot - ctx->add_dict - ctx->add_weak; | |
| 2576 | 279850 | PyObject *new_slots = PyList_New(new_nslot); | |
| 2577 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 279850 times.
|
279850 | if (new_slots == NULL) { |
| 2578 | ✗ | return NULL; | |
| 2579 | } | ||
| 2580 | |||
| 2581 | 279850 | Py_ssize_t j = 0; | |
| 2582 |
2/2✓ Branch 0 taken 251284 times.
✓ Branch 1 taken 279850 times.
|
531134 | for (Py_ssize_t i = 0; i < nslot; i++) { |
| 2583 | 251284 | PyObject *slot = PyTuple_GET_ITEM(slots, i); | |
| 2584 |
4/4✓ Branch 0 taken 12461 times.
✓ Branch 1 taken 238823 times.
✓ Branch 3 taken 9960 times.
✓ Branch 4 taken 2501 times.
|
251284 | if ((ctx->add_dict && _PyUnicode_Equal(slot, &_Py_ID(__dict__))) || |
| 2585 |
4/4✓ Branch 0 taken 39838 times.
✓ Branch 1 taken 208945 times.
✓ Branch 3 taken 10700 times.
✓ Branch 4 taken 29138 times.
|
248783 | (ctx->add_weak && _PyUnicode_Equal(slot, &_Py_ID(__weakref__)))) |
| 2586 | { | ||
| 2587 | 13201 | continue; | |
| 2588 | } | ||
| 2589 | |||
| 2590 | 238083 | slot =_Py_Mangle(ctx->name, slot); | |
| 2591 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 238083 times.
|
238083 | if (!slot) { |
| 2592 | ✗ | goto error; | |
| 2593 | } | ||
| 2594 | 238083 | PyList_SET_ITEM(new_slots, j, slot); | |
| 2595 | |||
| 2596 | 238083 | int r = PyDict_Contains(dict, slot); | |
| 2597 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 238083 times.
|
238083 | if (r < 0) { |
| 2598 | ✗ | goto error; | |
| 2599 | } | ||
| 2600 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 238083 times.
|
238083 | if (r > 0) { |
| 2601 | /* CPython inserts __qualname__ and __classcell__ (when needed) | ||
| 2602 | into the namespace when creating a class. They will be deleted | ||
| 2603 | below so won't act as class variables. */ | ||
| 2604 | ✗ | if (!_PyUnicode_Equal(slot, &_Py_ID(__qualname__)) && | |
| 2605 | ✗ | !_PyUnicode_Equal(slot, &_Py_ID(__classcell__))) | |
| 2606 | { | ||
| 2607 | ✗ | PyErr_Format(PyExc_ValueError, | |
| 2608 | "%R in __slots__ conflicts with class variable", | ||
| 2609 | slot); | ||
| 2610 | ✗ | goto error; | |
| 2611 | } | ||
| 2612 | } | ||
| 2613 | |||
| 2614 | 238083 | j++; | |
| 2615 | } | ||
| 2616 | assert(j == new_nslot); | ||
| 2617 | |||
| 2618 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 279850 times.
|
279850 | if (PyList_Sort(new_slots) == -1) { |
| 2619 | ✗ | goto error; | |
| 2620 | } | ||
| 2621 | |||
| 2622 | 279850 | PyObject *tuple = PyList_AsTuple(new_slots); | |
| 2623 | 279850 | Py_DECREF(new_slots); | |
| 2624 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 279850 times.
|
279850 | if (tuple == NULL) { |
| 2625 | ✗ | return NULL; | |
| 2626 | } | ||
| 2627 | |||
| 2628 | assert(PyTuple_GET_SIZE(tuple) == new_nslot); | ||
| 2629 | 279850 | return tuple; | |
| 2630 | |||
| 2631 | ✗ | error: | |
| 2632 | ✗ | Py_DECREF(new_slots); | |
| 2633 | ✗ | return NULL; | |
| 2634 | } | ||
| 2635 | |||
| 2636 | |||
| 2637 | static void | ||
| 2638 | 279850 | type_new_slots_bases(type_new_ctx *ctx) | |
| 2639 | { | ||
| 2640 | 279850 | Py_ssize_t nbases = PyTuple_GET_SIZE(ctx->bases); | |
| 2641 |
2/2✓ Branch 0 taken 23429 times.
✓ Branch 1 taken 256421 times.
|
279850 | if (nbases > 1 && |
| 2642 |
3/4✓ Branch 0 taken 23061 times.
✓ Branch 1 taken 368 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 23061 times.
|
23429 | ((ctx->may_add_dict && ctx->add_dict == 0) || |
| 2643 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 368 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
368 | (ctx->may_add_weak && ctx->add_weak == 0))) |
| 2644 | { | ||
| 2645 |
2/2✓ Branch 0 taken 49544 times.
✓ Branch 1 taken 22246 times.
|
71790 | for (Py_ssize_t i = 0; i < nbases; i++) { |
| 2646 | 49544 | PyObject *obj = PyTuple_GET_ITEM(ctx->bases, i); | |
| 2647 |
2/2✓ Branch 0 taken 22929 times.
✓ Branch 1 taken 26615 times.
|
49544 | if (obj == (PyObject *)ctx->base) { |
| 2648 | /* Skip primary base */ | ||
| 2649 | 22929 | continue; | |
| 2650 | } | ||
| 2651 | 26615 | PyTypeObject *base = _PyType_CAST(obj); | |
| 2652 | |||
| 2653 |
2/4✓ Branch 0 taken 26615 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 26615 times.
✗ Branch 3 not taken.
|
26615 | if (ctx->may_add_dict && ctx->add_dict == 0 && |
| 2654 |
2/2✓ Branch 0 taken 815 times.
✓ Branch 1 taken 25800 times.
|
26615 | base->tp_dictoffset != 0) |
| 2655 | { | ||
| 2656 | 815 | ctx->add_dict++; | |
| 2657 | } | ||
| 2658 |
4/4✓ Branch 0 taken 23264 times.
✓ Branch 1 taken 3351 times.
✓ Branch 2 taken 22754 times.
✓ Branch 3 taken 510 times.
|
26615 | if (ctx->may_add_weak && ctx->add_weak == 0 && |
| 2659 |
2/2✓ Branch 0 taken 815 times.
✓ Branch 1 taken 21939 times.
|
22754 | base->tp_weaklistoffset != 0) |
| 2660 | { | ||
| 2661 | 815 | ctx->add_weak++; | |
| 2662 | } | ||
| 2663 |
3/4✓ Branch 0 taken 26615 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 25800 times.
✓ Branch 3 taken 815 times.
|
26615 | if (ctx->may_add_dict && ctx->add_dict == 0) { |
| 2664 | 25800 | continue; | |
| 2665 | } | ||
| 2666 |
2/4✓ Branch 0 taken 815 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 815 times.
|
815 | if (ctx->may_add_weak && ctx->add_weak == 0) { |
| 2667 | ✗ | continue; | |
| 2668 | } | ||
| 2669 | /* Nothing more to check */ | ||
| 2670 | 815 | break; | |
| 2671 | } | ||
| 2672 | } | ||
| 2673 | 279850 | } | |
| 2674 | |||
| 2675 | |||
| 2676 | static int | ||
| 2677 | 279850 | type_new_slots_impl(type_new_ctx *ctx, PyObject *dict) | |
| 2678 | { | ||
| 2679 | /* Are slots allowed? */ | ||
| 2680 |
3/4✓ Branch 0 taken 66677 times.
✓ Branch 1 taken 213173 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 66677 times.
|
279850 | if (ctx->nslot > 0 && ctx->base->tp_itemsize != 0) { |
| 2681 | ✗ | PyErr_Format(PyExc_TypeError, | |
| 2682 | "nonempty __slots__ not supported for subtype of '%s'", | ||
| 2683 | ✗ | ctx->base->tp_name); | |
| 2684 | ✗ | return -1; | |
| 2685 | } | ||
| 2686 | |||
| 2687 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 279850 times.
|
279850 | if (type_new_visit_slots(ctx) < 0) { |
| 2688 | ✗ | return -1; | |
| 2689 | } | ||
| 2690 | |||
| 2691 | 279850 | PyObject *new_slots = type_new_copy_slots(ctx, dict); | |
| 2692 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 279850 times.
|
279850 | if (new_slots == NULL) { |
| 2693 | ✗ | return -1; | |
| 2694 | } | ||
| 2695 | assert(PyTuple_CheckExact(new_slots)); | ||
| 2696 | |||
| 2697 | 279850 | Py_XSETREF(ctx->slots, new_slots); | |
| 2698 | 279850 | ctx->nslot = PyTuple_GET_SIZE(new_slots); | |
| 2699 | |||
| 2700 | /* Secondary bases may provide weakrefs or dict */ | ||
| 2701 | 279850 | type_new_slots_bases(ctx); | |
| 2702 | 279850 | return 0; | |
| 2703 | } | ||
| 2704 | |||
| 2705 | |||
| 2706 | static Py_ssize_t | ||
| 2707 | 1582753 | type_new_slots(type_new_ctx *ctx, PyObject *dict) | |
| 2708 | { | ||
| 2709 | // Check for a __slots__ sequence variable in dict, and count it | ||
| 2710 | 1582753 | ctx->add_dict = 0; | |
| 2711 | 1582753 | ctx->add_weak = 0; | |
| 2712 | 1582753 | ctx->may_add_dict = (ctx->base->tp_dictoffset == 0); | |
| 2713 | 3165506 | ctx->may_add_weak = (ctx->base->tp_weaklistoffset == 0 | |
| 2714 |
4/4✓ Branch 0 taken 947050 times.
✓ Branch 1 taken 635703 times.
✓ Branch 2 taken 798843 times.
✓ Branch 3 taken 148207 times.
|
1582753 | && ctx->base->tp_itemsize == 0); |
| 2715 | |||
| 2716 |
2/2✓ Branch 0 taken 1302903 times.
✓ Branch 1 taken 279850 times.
|
1582753 | if (ctx->slots == NULL) { |
| 2717 |
2/2✓ Branch 0 taken 508799 times.
✓ Branch 1 taken 794104 times.
|
1302903 | if (ctx->may_add_dict) { |
| 2718 | 508799 | ctx->add_dict++; | |
| 2719 | } | ||
| 2720 |
2/2✓ Branch 0 taken 622412 times.
✓ Branch 1 taken 680491 times.
|
1302903 | if (ctx->may_add_weak) { |
| 2721 | 622412 | ctx->add_weak++; | |
| 2722 | } | ||
| 2723 | } | ||
| 2724 | else { | ||
| 2725 | /* Have slots */ | ||
| 2726 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 279850 times.
|
279850 | if (type_new_slots_impl(ctx, dict) < 0) { |
| 2727 | ✗ | return -1; | |
| 2728 | } | ||
| 2729 | } | ||
| 2730 | 1582753 | return 0; | |
| 2731 | } | ||
| 2732 | |||
| 2733 | |||
| 2734 | static PyTypeObject* | ||
| 2735 | 1582753 | type_new_alloc(type_new_ctx *ctx) | |
| 2736 | { | ||
| 2737 | 1582753 | PyTypeObject *metatype = ctx->metatype; | |
| 2738 | PyTypeObject *type; | ||
| 2739 | |||
| 2740 | // Allocate the type object | ||
| 2741 | 1582753 | type = (PyTypeObject *)metatype->tp_alloc(metatype, ctx->nslot); | |
| 2742 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1582753 times.
|
1582753 | if (type == NULL) { |
| 2743 | ✗ | return NULL; | |
| 2744 | } | ||
| 2745 | 1582753 | PyHeapTypeObject *et = (PyHeapTypeObject *)type; | |
| 2746 | |||
| 2747 | // Initialize tp_flags. | ||
| 2748 | // All heap types need GC, since we can create a reference cycle by storing | ||
| 2749 | // an instance on one of its parents. | ||
| 2750 | 1582753 | type->tp_flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HEAPTYPE | | |
| 2751 | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC); | ||
| 2752 | |||
| 2753 | // Initialize essential fields | ||
| 2754 | 1582753 | type->tp_as_async = &et->as_async; | |
| 2755 | 1582753 | type->tp_as_number = &et->as_number; | |
| 2756 | 1582753 | type->tp_as_sequence = &et->as_sequence; | |
| 2757 | 1582753 | type->tp_as_mapping = &et->as_mapping; | |
| 2758 | 1582753 | type->tp_as_buffer = &et->as_buffer; | |
| 2759 | |||
| 2760 | 1582753 | type->tp_bases = Py_NewRef(ctx->bases); | |
| 2761 | 1582753 | type->tp_base = (PyTypeObject *)Py_NewRef(ctx->base); | |
| 2762 | |||
| 2763 | 1582753 | type->tp_dealloc = subtype_dealloc; | |
| 2764 | /* Always override allocation strategy to use regular heap */ | ||
| 2765 | 1582753 | type->tp_alloc = PyType_GenericAlloc; | |
| 2766 | 1582753 | type->tp_free = PyObject_GC_Del; | |
| 2767 | |||
| 2768 | 1582753 | type->tp_traverse = subtype_traverse; | |
| 2769 | 1582753 | type->tp_clear = subtype_clear; | |
| 2770 | |||
| 2771 | 1582753 | et->ht_name = Py_NewRef(ctx->name); | |
| 2772 | 1582753 | et->ht_module = NULL; | |
| 2773 | 1582753 | et->_ht_tpname = NULL; | |
| 2774 | |||
| 2775 | 1582753 | return type; | |
| 2776 | } | ||
| 2777 | |||
| 2778 | |||
| 2779 | static int | ||
| 2780 | 1582753 | type_new_set_name(const type_new_ctx *ctx, PyTypeObject *type) | |
| 2781 | { | ||
| 2782 | Py_ssize_t name_size; | ||
| 2783 | 1582753 | type->tp_name = PyUnicode_AsUTF8AndSize(ctx->name, &name_size); | |
| 2784 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1582753 times.
|
1582753 | if (!type->tp_name) { |
| 2785 | ✗ | return -1; | |
| 2786 | } | ||
| 2787 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1582753 times.
|
1582753 | if (strlen(type->tp_name) != (size_t)name_size) { |
| 2788 | ✗ | PyErr_SetString(PyExc_ValueError, | |
| 2789 | "type name must not contain null characters"); | ||
| 2790 | ✗ | return -1; | |
| 2791 | } | ||
| 2792 | 1582753 | return 0; | |
| 2793 | } | ||
| 2794 | |||
| 2795 | |||
| 2796 | /* Set __module__ in the dict */ | ||
| 2797 | static int | ||
| 2798 | 1582753 | type_new_set_module(PyTypeObject *type) | |
| 2799 | { | ||
| 2800 | 1582753 | int r = PyDict_Contains(type->tp_dict, &_Py_ID(__module__)); | |
| 2801 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1582753 times.
|
1582753 | if (r < 0) { |
| 2802 | ✗ | return -1; | |
| 2803 | } | ||
| 2804 |
2/2✓ Branch 0 taken 1476443 times.
✓ Branch 1 taken 106310 times.
|
1582753 | if (r > 0) { |
| 2805 | 1476443 | return 0; | |
| 2806 | } | ||
| 2807 | |||
| 2808 | 106310 | PyObject *globals = PyEval_GetGlobals(); | |
| 2809 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 106310 times.
|
106310 | if (globals == NULL) { |
| 2810 | ✗ | return 0; | |
| 2811 | } | ||
| 2812 | |||
| 2813 | 106310 | PyObject *module = PyDict_GetItemWithError(globals, &_Py_ID(__name__)); | |
| 2814 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 106310 times.
|
106310 | if (module == NULL) { |
| 2815 | ✗ | if (PyErr_Occurred()) { | |
| 2816 | ✗ | return -1; | |
| 2817 | } | ||
| 2818 | ✗ | return 0; | |
| 2819 | } | ||
| 2820 | |||
| 2821 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 106310 times.
|
106310 | if (PyDict_SetItem(type->tp_dict, &_Py_ID(__module__), module) < 0) { |
| 2822 | ✗ | return -1; | |
| 2823 | } | ||
| 2824 | 106310 | return 0; | |
| 2825 | } | ||
| 2826 | |||
| 2827 | |||
| 2828 | /* Set ht_qualname to dict['__qualname__'] if available, else to | ||
| 2829 | __name__. The __qualname__ accessor will look for ht_qualname. */ | ||
| 2830 | static int | ||
| 2831 | 1582753 | type_new_set_ht_name(PyTypeObject *type) | |
| 2832 | { | ||
| 2833 | 1582753 | PyHeapTypeObject *et = (PyHeapTypeObject *)type; | |
| 2834 | 1582753 | PyObject *qualname = PyDict_GetItemWithError( | |
| 2835 | type->tp_dict, &_Py_ID(__qualname__)); | ||
| 2836 |
2/2✓ Branch 0 taken 1283092 times.
✓ Branch 1 taken 299661 times.
|
1582753 | if (qualname != NULL) { |
| 2837 |
1/2✗ Branch 2 not taken.
✓ Branch 3 taken 1283092 times.
|
1283092 | if (!PyUnicode_Check(qualname)) { |
| 2838 | ✗ | PyErr_Format(PyExc_TypeError, | |
| 2839 | "type __qualname__ must be a str, not %s", | ||
| 2840 | ✗ | Py_TYPE(qualname)->tp_name); | |
| 2841 | ✗ | return -1; | |
| 2842 | } | ||
| 2843 | 1283092 | et->ht_qualname = Py_NewRef(qualname); | |
| 2844 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 1283092 times.
|
1283092 | if (PyDict_DelItem(type->tp_dict, &_Py_ID(__qualname__)) < 0) { |
| 2845 | ✗ | return -1; | |
| 2846 | } | ||
| 2847 | } | ||
| 2848 | else { | ||
| 2849 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 299661 times.
|
299661 | if (PyErr_Occurred()) { |
| 2850 | ✗ | return -1; | |
| 2851 | } | ||
| 2852 | 299661 | et->ht_qualname = Py_NewRef(et->ht_name); | |
| 2853 | } | ||
| 2854 | 1582753 | return 0; | |
| 2855 | } | ||
| 2856 | |||
| 2857 | |||
| 2858 | /* Set tp_doc to a copy of dict['__doc__'], if the latter is there | ||
| 2859 | and is a string. The __doc__ accessor will first look for tp_doc; | ||
| 2860 | if that fails, it will still look into __dict__. */ | ||
| 2861 | static int | ||
| 2862 | 1582753 | type_new_set_doc(PyTypeObject *type) | |
| 2863 | { | ||
| 2864 | 1582753 | PyObject *doc = PyDict_GetItemWithError(type->tp_dict, &_Py_ID(__doc__)); | |
| 2865 |
2/2✓ Branch 0 taken 544273 times.
✓ Branch 1 taken 1038480 times.
|
1582753 | if (doc == NULL) { |
| 2866 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 544273 times.
|
544273 | if (PyErr_Occurred()) { |
| 2867 | ✗ | return -1; | |
| 2868 | } | ||
| 2869 | // no __doc__ key | ||
| 2870 | 544273 | return 0; | |
| 2871 | } | ||
| 2872 |
2/2✓ Branch 2 taken 340 times.
✓ Branch 3 taken 1038140 times.
|
1038480 | if (!PyUnicode_Check(doc)) { |
| 2873 | // ignore non-string __doc__ | ||
| 2874 | 340 | return 0; | |
| 2875 | } | ||
| 2876 | |||
| 2877 | 1038140 | const char *doc_str = PyUnicode_AsUTF8(doc); | |
| 2878 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1038140 times.
|
1038140 | if (doc_str == NULL) { |
| 2879 | ✗ | return -1; | |
| 2880 | } | ||
| 2881 | |||
| 2882 | // Silently truncate the docstring if it contains a null byte | ||
| 2883 | 1038140 | Py_ssize_t size = strlen(doc_str) + 1; | |
| 2884 | 1038140 | char *tp_doc = (char *)PyObject_Malloc(size); | |
| 2885 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1038140 times.
|
1038140 | if (tp_doc == NULL) { |
| 2886 | ✗ | PyErr_NoMemory(); | |
| 2887 | ✗ | return -1; | |
| 2888 | } | ||
| 2889 | |||
| 2890 | 1038140 | memcpy(tp_doc, doc_str, size); | |
| 2891 | 1038140 | type->tp_doc = tp_doc; | |
| 2892 | 1038140 | return 0; | |
| 2893 | } | ||
| 2894 | |||
| 2895 | |||
| 2896 | static int | ||
| 2897 | 1582753 | type_new_staticmethod(PyTypeObject *type, PyObject *attr) | |
| 2898 | { | ||
| 2899 | 1582753 | PyObject *func = PyDict_GetItemWithError(type->tp_dict, attr); | |
| 2900 |
2/2✓ Branch 0 taken 1418384 times.
✓ Branch 1 taken 164369 times.
|
1582753 | if (func == NULL) { |
| 2901 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 1418384 times.
|
1418384 | if (PyErr_Occurred()) { |
| 2902 | ✗ | return -1; | |
| 2903 | } | ||
| 2904 | 1418384 | return 0; | |
| 2905 | } | ||
| 2906 |
2/2✓ Branch 1 taken 674 times.
✓ Branch 2 taken 163695 times.
|
164369 | if (!PyFunction_Check(func)) { |
| 2907 | 674 | return 0; | |
| 2908 | } | ||
| 2909 | |||
| 2910 | 163695 | PyObject *static_func = PyStaticMethod_New(func); | |
| 2911 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 163695 times.
|
163695 | if (static_func == NULL) { |
| 2912 | ✗ | return -1; | |
| 2913 | } | ||
| 2914 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 163695 times.
|
163695 | if (PyDict_SetItem(type->tp_dict, attr, static_func) < 0) { |
| 2915 | ✗ | Py_DECREF(static_func); | |
| 2916 | ✗ | return -1; | |
| 2917 | } | ||
| 2918 | 163695 | Py_DECREF(static_func); | |
| 2919 | 163695 | return 0; | |
| 2920 | } | ||
| 2921 | |||
| 2922 | |||
| 2923 | static int | ||
| 2924 | 3165506 | type_new_classmethod(PyTypeObject *type, PyObject *attr) | |
| 2925 | { | ||
| 2926 | 3165506 | PyObject *func = PyDict_GetItemWithError(type->tp_dict, attr); | |
| 2927 |
2/2✓ Branch 0 taken 3113655 times.
✓ Branch 1 taken 51851 times.
|
3165506 | if (func == NULL) { |
| 2928 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 3113655 times.
|
3113655 | if (PyErr_Occurred()) { |
| 2929 | ✗ | return -1; | |
| 2930 | } | ||
| 2931 | 3113655 | return 0; | |
| 2932 | } | ||
| 2933 |
2/2✓ Branch 1 taken 44731 times.
✓ Branch 2 taken 7120 times.
|
51851 | if (!PyFunction_Check(func)) { |
| 2934 | 44731 | return 0; | |
| 2935 | } | ||
| 2936 | |||
| 2937 | 7120 | PyObject *method = PyClassMethod_New(func); | |
| 2938 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 7120 times.
|
7120 | if (method == NULL) { |
| 2939 | ✗ | return -1; | |
| 2940 | } | ||
| 2941 | |||
| 2942 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 7120 times.
|
7120 | if (PyDict_SetItem(type->tp_dict, attr, method) < 0) { |
| 2943 | ✗ | Py_DECREF(method); | |
| 2944 | ✗ | return -1; | |
| 2945 | } | ||
| 2946 | 7120 | Py_DECREF(method); | |
| 2947 | 7120 | return 0; | |
| 2948 | } | ||
| 2949 | |||
| 2950 | |||
| 2951 | /* Add descriptors for custom slots from __slots__, or for __dict__ */ | ||
| 2952 | static int | ||
| 2953 | 1582753 | type_new_descriptors(const type_new_ctx *ctx, PyTypeObject *type) | |
| 2954 | { | ||
| 2955 | 1582753 | PyHeapTypeObject *et = (PyHeapTypeObject *)type; | |
| 2956 | 1582753 | Py_ssize_t slotoffset = ctx->base->tp_basicsize; | |
| 2957 |
2/2✓ Branch 0 taken 279850 times.
✓ Branch 1 taken 1302903 times.
|
1582753 | if (et->ht_slots != NULL) { |
| 2958 | 279850 | PyMemberDef *mp = _PyHeapType_GET_MEMBERS(et); | |
| 2959 | 279850 | Py_ssize_t nslot = PyTuple_GET_SIZE(et->ht_slots); | |
| 2960 |
2/2✓ Branch 0 taken 238083 times.
✓ Branch 1 taken 279850 times.
|
517933 | for (Py_ssize_t i = 0; i < nslot; i++, mp++) { |
| 2961 | 476166 | mp->name = PyUnicode_AsUTF8( | |
| 2962 | 238083 | PyTuple_GET_ITEM(et->ht_slots, i)); | |
| 2963 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 238083 times.
|
238083 | if (mp->name == NULL) { |
| 2964 | ✗ | return -1; | |
| 2965 | } | ||
| 2966 | 238083 | mp->type = T_OBJECT_EX; | |
| 2967 | 238083 | mp->offset = slotoffset; | |
| 2968 | |||
| 2969 | /* __dict__ and __weakref__ are already filtered out */ | ||
| 2970 | assert(strcmp(mp->name, "__dict__") != 0); | ||
| 2971 | assert(strcmp(mp->name, "__weakref__") != 0); | ||
| 2972 | |||
| 2973 | 238083 | slotoffset += sizeof(PyObject *); | |
| 2974 | } | ||
| 2975 | } | ||
| 2976 | |||
| 2977 |
4/4✓ Branch 0 taken 512115 times.
✓ Branch 1 taken 1070638 times.
✓ Branch 2 taken 20586 times.
✓ Branch 3 taken 491529 times.
|
1582753 | if (ctx->add_dict && ctx->base->tp_itemsize) { |
| 2978 | 20586 | type->tp_dictoffset = -(long)sizeof(PyObject *); | |
| 2979 | 20586 | slotoffset += sizeof(PyObject *); | |
| 2980 | } | ||
| 2981 | |||
| 2982 |
2/2✓ Branch 0 taken 633927 times.
✓ Branch 1 taken 948826 times.
|
1582753 | if (ctx->add_weak) { |
| 2983 | assert(!ctx->base->tp_itemsize); | ||
| 2984 | 633927 | type->tp_weaklistoffset = slotoffset; | |
| 2985 | 633927 | slotoffset += sizeof(PyObject *); | |
| 2986 | } | ||
| 2987 |
4/4✓ Branch 0 taken 512115 times.
✓ Branch 1 taken 1070638 times.
✓ Branch 2 taken 491529 times.
✓ Branch 3 taken 20586 times.
|
1582753 | if (ctx->add_dict && ctx->base->tp_itemsize == 0) { |
| 2988 | assert((type->tp_flags & Py_TPFLAGS_MANAGED_DICT) == 0); | ||
| 2989 | 491529 | type->tp_flags |= Py_TPFLAGS_MANAGED_DICT; | |
| 2990 | 491529 | type->tp_dictoffset = -slotoffset - sizeof(PyObject *)*3; | |
| 2991 | } | ||
| 2992 | |||
| 2993 | 1582753 | type->tp_basicsize = slotoffset; | |
| 2994 | 1582753 | type->tp_itemsize = ctx->base->tp_itemsize; | |
| 2995 | 1582753 | type->tp_members = _PyHeapType_GET_MEMBERS(et); | |
| 2996 | 1582753 | return 0; | |
| 2997 | } | ||
| 2998 | |||
| 2999 | |||
| 3000 | static void | ||
| 3001 | 1582753 | type_new_set_slots(const type_new_ctx *ctx, PyTypeObject *type) | |
| 3002 | { | ||
| 3003 |
4/4✓ Branch 0 taken 633927 times.
✓ Branch 1 taken 948826 times.
✓ Branch 2 taken 484463 times.
✓ Branch 3 taken 149464 times.
|
1582753 | if (type->tp_weaklistoffset && type->tp_dictoffset) { |
| 3004 | 484463 | type->tp_getset = subtype_getsets_full; | |
| 3005 | } | ||
| 3006 |
3/4✓ Branch 0 taken 149464 times.
✓ Branch 1 taken 948826 times.
✓ Branch 2 taken 149464 times.
✗ Branch 3 not taken.
|
1098290 | else if (type->tp_weaklistoffset && !type->tp_dictoffset) { |
| 3007 | 149464 | type->tp_getset = subtype_getsets_weakref_only; | |
| 3008 | } | ||
| 3009 |
3/4✓ Branch 0 taken 948826 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 27652 times.
✓ Branch 3 taken 921174 times.
|
948826 | else if (!type->tp_weaklistoffset && type->tp_dictoffset) { |
| 3010 | 27652 | type->tp_getset = subtype_getsets_dict_only; | |
| 3011 | } | ||
| 3012 | else { | ||
| 3013 | 921174 | type->tp_getset = NULL; | |
| 3014 | } | ||
| 3015 | |||
| 3016 | /* Special case some slots */ | ||
| 3017 |
4/4✓ Branch 0 taken 1070638 times.
✓ Branch 1 taken 512115 times.
✓ Branch 2 taken 62786 times.
✓ Branch 3 taken 1007852 times.
|
1582753 | if (type->tp_dictoffset != 0 || ctx->nslot > 0) { |
| 3018 | 574901 | PyTypeObject *base = ctx->base; | |
| 3019 |
2/4✓ Branch 0 taken 574901 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 574901 times.
|
574901 | if (base->tp_getattr == NULL && base->tp_getattro == NULL) { |
| 3020 | ✗ | type->tp_getattro = PyObject_GenericGetAttr; | |
| 3021 | } | ||
| 3022 |
2/4✓ Branch 0 taken 574901 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 574901 times.
|
574901 | if (base->tp_setattr == NULL && base->tp_setattro == NULL) { |
| 3023 | ✗ | type->tp_setattro = PyObject_GenericSetAttr; | |
| 3024 | } | ||
| 3025 | } | ||
| 3026 | 1582753 | } | |
| 3027 | |||
| 3028 | |||
| 3029 | /* store type in class' cell if one is supplied */ | ||
| 3030 | static int | ||
| 3031 | 1582753 | type_new_set_classcell(PyTypeObject *type) | |
| 3032 | { | ||
| 3033 | 1582753 | PyObject *cell = PyDict_GetItemWithError( | |
| 3034 | type->tp_dict, &_Py_ID(__classcell__)); | ||
| 3035 |
2/2✓ Branch 0 taken 1389624 times.
✓ Branch 1 taken 193129 times.
|
1582753 | if (cell == NULL) { |
| 3036 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 1389624 times.
|
1389624 | if (PyErr_Occurred()) { |
| 3037 | ✗ | return -1; | |
| 3038 | } | ||
| 3039 | 1389624 | return 0; | |
| 3040 | } | ||
| 3041 | |||
| 3042 | /* At least one method requires a reference to its defining class */ | ||
| 3043 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 193129 times.
|
193129 | if (!PyCell_Check(cell)) { |
| 3044 | ✗ | PyErr_Format(PyExc_TypeError, | |
| 3045 | "__classcell__ must be a nonlocal cell, not %.200R", | ||
| 3046 | Py_TYPE(cell)); | ||
| 3047 | ✗ | return -1; | |
| 3048 | } | ||
| 3049 | |||
| 3050 | 193129 | (void)PyCell_Set(cell, (PyObject *) type); | |
| 3051 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 193129 times.
|
193129 | if (PyDict_DelItem(type->tp_dict, &_Py_ID(__classcell__)) < 0) { |
| 3052 | ✗ | return -1; | |
| 3053 | } | ||
| 3054 | 193129 | return 0; | |
| 3055 | } | ||
| 3056 | |||
| 3057 | |||
| 3058 | static int | ||
| 3059 | 1582753 | type_new_set_attrs(const type_new_ctx *ctx, PyTypeObject *type) | |
| 3060 | { | ||
| 3061 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 1582753 times.
|
1582753 | if (type_new_set_name(ctx, type) < 0) { |
| 3062 | ✗ | return -1; | |
| 3063 | } | ||
| 3064 | |||
| 3065 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 1582753 times.
|
1582753 | if (type_new_set_module(type) < 0) { |
| 3066 | ✗ | return -1; | |
| 3067 | } | ||
| 3068 | |||
| 3069 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 1582753 times.
|
1582753 | if (type_new_set_ht_name(type) < 0) { |
| 3070 | ✗ | return -1; | |
| 3071 | } | ||
| 3072 | |||
| 3073 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 1582753 times.
|
1582753 | if (type_new_set_doc(type) < 0) { |
| 3074 | ✗ | return -1; | |
| 3075 | } | ||
| 3076 | |||
| 3077 | /* Special-case __new__: if it's a plain function, | ||
| 3078 | make it a static function */ | ||
| 3079 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 1582753 times.
|
1582753 | if (type_new_staticmethod(type, &_Py_ID(__new__)) < 0) { |
| 3080 | ✗ | return -1; | |
| 3081 | } | ||
| 3082 | |||
| 3083 | /* Special-case __init_subclass__ and __class_getitem__: | ||
| 3084 | if they are plain functions, make them classmethods */ | ||
| 3085 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 1582753 times.
|
1582753 | if (type_new_classmethod(type, &_Py_ID(__init_subclass__)) < 0) { |
| 3086 | ✗ | return -1; | |
| 3087 | } | ||
| 3088 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 1582753 times.
|
1582753 | if (type_new_classmethod(type, &_Py_ID(__class_getitem__)) < 0) { |
| 3089 | ✗ | return -1; | |
| 3090 | } | ||
| 3091 | |||
| 3092 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 1582753 times.
|
1582753 | if (type_new_descriptors(ctx, type) < 0) { |
| 3093 | ✗ | return -1; | |
| 3094 | } | ||
| 3095 | |||
| 3096 | 1582753 | type_new_set_slots(ctx, type); | |
| 3097 | |||
| 3098 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 1582753 times.
|
1582753 | if (type_new_set_classcell(type) < 0) { |
| 3099 | ✗ | return -1; | |
| 3100 | } | ||
| 3101 | 1582753 | return 0; | |
| 3102 | } | ||
| 3103 | |||
| 3104 | |||
| 3105 | static int | ||
| 3106 | 1582753 | type_new_get_slots(type_new_ctx *ctx, PyObject *dict) | |
| 3107 | { | ||
| 3108 | 1582753 | PyObject *slots = PyDict_GetItemWithError(dict, &_Py_ID(__slots__)); | |
| 3109 |
2/2✓ Branch 0 taken 1302903 times.
✓ Branch 1 taken 279850 times.
|
1582753 | if (slots == NULL) { |
| 3110 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 1302903 times.
|
1302903 | if (PyErr_Occurred()) { |
| 3111 | ✗ | return -1; | |
| 3112 | } | ||
| 3113 | 1302903 | ctx->slots = NULL; | |
| 3114 | 1302903 | ctx->nslot = 0; | |
| 3115 | 1302903 | return 0; | |
| 3116 | } | ||
| 3117 | |||
| 3118 | // Make it into a tuple | ||
| 3119 | PyObject *new_slots; | ||
| 3120 |
2/2✓ Branch 2 taken 2523 times.
✓ Branch 3 taken 277327 times.
|
279850 | if (PyUnicode_Check(slots)) { |
| 3121 | 2523 | new_slots = PyTuple_Pack(1, slots); | |
| 3122 | } | ||
| 3123 | else { | ||
| 3124 | 277327 | new_slots = PySequence_Tuple(slots); | |
| 3125 | } | ||
| 3126 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 279850 times.
|
279850 | if (new_slots == NULL) { |
| 3127 | ✗ | return -1; | |
| 3128 | } | ||
| 3129 | assert(PyTuple_CheckExact(new_slots)); | ||
| 3130 | 279850 | ctx->slots = new_slots; | |
| 3131 | 279850 | ctx->nslot = PyTuple_GET_SIZE(new_slots); | |
| 3132 | 279850 | return 0; | |
| 3133 | } | ||
| 3134 | |||
| 3135 | |||
| 3136 | static PyTypeObject* | ||
| 3137 | 1582753 | type_new_init(type_new_ctx *ctx) | |
| 3138 | { | ||
| 3139 | 1582753 | PyObject *dict = PyDict_Copy(ctx->orig_dict); | |
| 3140 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1582753 times.
|
1582753 | if (dict == NULL) { |
| 3141 | ✗ | goto error; | |
| 3142 | } | ||
| 3143 | |||
| 3144 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 1582753 times.
|
1582753 | if (type_new_get_slots(ctx, dict) < 0) { |
| 3145 | ✗ | goto error; | |
| 3146 | } | ||
| 3147 | assert(!PyErr_Occurred()); | ||
| 3148 | |||
| 3149 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 1582753 times.
|
1582753 | if (type_new_slots(ctx, dict) < 0) { |
| 3150 | ✗ | goto error; | |
| 3151 | } | ||
| 3152 | |||
| 3153 | 1582753 | PyTypeObject *type = type_new_alloc(ctx); | |
| 3154 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1582753 times.
|
1582753 | if (type == NULL) { |
| 3155 | ✗ | goto error; | |
| 3156 | } | ||
| 3157 | |||
| 3158 | 1582753 | type->tp_dict = dict; | |
| 3159 | |||
| 3160 | 1582753 | PyHeapTypeObject *et = (PyHeapTypeObject*)type; | |
| 3161 | 1582753 | et->ht_slots = ctx->slots; | |
| 3162 | 1582753 | ctx->slots = NULL; | |
| 3163 | |||
| 3164 | 1582753 | return type; | |
| 3165 | |||
| 3166 | ✗ | error: | |
| 3167 | ✗ | Py_CLEAR(ctx->slots); | |
| 3168 | ✗ | Py_XDECREF(dict); | |
| 3169 | ✗ | return NULL; | |
| 3170 | } | ||
| 3171 | |||
| 3172 | |||
| 3173 | static PyObject* | ||
| 3174 | 1582753 | type_new_impl(type_new_ctx *ctx) | |
| 3175 | { | ||
| 3176 | 1582753 | PyTypeObject *type = type_new_init(ctx); | |
| 3177 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1582753 times.
|
1582753 | if (type == NULL) { |
| 3178 | ✗ | return NULL; | |
| 3179 | } | ||
| 3180 | |||
| 3181 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 1582753 times.
|
1582753 | if (type_new_set_attrs(ctx, type) < 0) { |
| 3182 | ✗ | goto error; | |
| 3183 | } | ||
| 3184 | |||
| 3185 | /* Initialize the rest */ | ||
| 3186 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 1582753 times.
|
1582753 | if (PyType_Ready(type) < 0) { |
| 3187 | ✗ | goto error; | |
| 3188 | } | ||
| 3189 | |||
| 3190 | // Put the proper slots in place | ||
| 3191 | 1582753 | fixup_slot_dispatchers(type); | |
| 3192 | |||
| 3193 |
2/2✓ Branch 0 taken 882289 times.
✓ Branch 1 taken 700464 times.
|
1582753 | if (type->tp_flags & Py_TPFLAGS_MANAGED_DICT) { |
| 3194 | 882289 | PyHeapTypeObject *et = (PyHeapTypeObject*)type; | |
| 3195 | 882289 | et->ht_cached_keys = _PyDict_NewKeysForClass(); | |
| 3196 | } | ||
| 3197 | |||
| 3198 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 1582753 times.
|
1582753 | if (type_new_set_names(type) < 0) { |
| 3199 | ✗ | goto error; | |
| 3200 | } | ||
| 3201 | |||
| 3202 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 1582753 times.
|
1582753 | if (type_new_init_subclass(type, ctx->kwds) < 0) { |
| 3203 | ✗ | goto error; | |
| 3204 | } | ||
| 3205 | |||
| 3206 | assert(_PyType_CheckConsistency(type)); | ||
| 3207 | |||
| 3208 | 1582753 | return (PyObject *)type; | |
| 3209 | |||
| 3210 | ✗ | error: | |
| 3211 | ✗ | Py_DECREF(type); | |
| 3212 | ✗ | return NULL; | |
| 3213 | } | ||
| 3214 | |||
| 3215 | |||
| 3216 | static int | ||
| 3217 | 1609449 | type_new_get_bases(type_new_ctx *ctx, PyObject **type) | |
| 3218 | { | ||
| 3219 | 1609449 | Py_ssize_t nbases = PyTuple_GET_SIZE(ctx->bases); | |
| 3220 |
2/2✓ Branch 0 taken 336657 times.
✓ Branch 1 taken 1272792 times.
|
1609449 | if (nbases == 0) { |
| 3221 | // Adjust for empty tuple bases | ||
| 3222 | 336657 | ctx->base = &PyBaseObject_Type; | |
| 3223 | 336657 | PyObject *new_bases = PyTuple_Pack(1, ctx->base); | |
| 3224 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 336657 times.
|
336657 | if (new_bases == NULL) { |
| 3225 | ✗ | return -1; | |
| 3226 | } | ||
| 3227 | 336657 | ctx->bases = new_bases; | |
| 3228 | 336657 | return 0; | |
| 3229 | } | ||
| 3230 | |||
| 3231 |
2/2✓ Branch 0 taken 1428402 times.
✓ Branch 1 taken 1272792 times.
|
2701194 | for (Py_ssize_t i = 0; i < nbases; i++) { |
| 3232 | 1428402 | PyObject *base = PyTuple_GET_ITEM(ctx->bases, i); | |
| 3233 |
1/2✓ Branch 1 taken 1428402 times.
✗ Branch 2 not taken.
|
1428402 | if (PyType_Check(base)) { |
| 3234 | 1428402 | continue; | |
| 3235 | } | ||
| 3236 | PyObject *mro_entries; | ||
| 3237 | ✗ | if (_PyObject_LookupAttr(base, &_Py_ID(__mro_entries__), | |
| 3238 | &mro_entries) < 0) { | ||
| 3239 | ✗ | return -1; | |
| 3240 | } | ||
| 3241 | ✗ | if (mro_entries != NULL) { | |
| 3242 | ✗ | PyErr_SetString(PyExc_TypeError, | |
| 3243 | "type() doesn't support MRO entry resolution; " | ||
| 3244 | "use types.new_class()"); | ||
| 3245 | ✗ | Py_DECREF(mro_entries); | |
| 3246 | ✗ | return -1; | |
| 3247 | } | ||
| 3248 | } | ||
| 3249 | |||
| 3250 | // Search the bases for the proper metatype to deal with this | ||
| 3251 | PyTypeObject *winner; | ||
| 3252 | 1272792 | winner = _PyType_CalculateMetaclass(ctx->metatype, ctx->bases); | |
| 3253 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1272792 times.
|
1272792 | if (winner == NULL) { |
| 3254 | ✗ | return -1; | |
| 3255 | } | ||
| 3256 | |||
| 3257 |
2/2✓ Branch 0 taken 30501 times.
✓ Branch 1 taken 1242291 times.
|
1272792 | if (winner != ctx->metatype) { |
| 3258 |
2/2✓ Branch 0 taken 26696 times.
✓ Branch 1 taken 3805 times.
|
30501 | if (winner->tp_new != type_new) { |
| 3259 | /* Pass it to the winner */ | ||
| 3260 | 26696 | *type = winner->tp_new(winner, ctx->args, ctx->kwds); | |
| 3261 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 26696 times.
|
26696 | if (*type == NULL) { |
| 3262 | ✗ | return -1; | |
| 3263 | } | ||
| 3264 | 26696 | return 1; | |
| 3265 | } | ||
| 3266 | |||
| 3267 | 3805 | ctx->metatype = winner; | |
| 3268 | } | ||
| 3269 | |||
| 3270 | /* Calculate best base, and check that all bases are type objects */ | ||
| 3271 | 1246096 | PyTypeObject *base = best_base(ctx->bases); | |
| 3272 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1246096 times.
|
1246096 | if (base == NULL) { |
| 3273 | ✗ | return -1; | |
| 3274 | } | ||
| 3275 | |||
| 3276 | 1246096 | ctx->base = base; | |
| 3277 | 1246096 | ctx->bases = Py_NewRef(ctx->bases); | |
| 3278 | 1246096 | return 0; | |
| 3279 | } | ||
| 3280 | |||
| 3281 | |||
| 3282 | static PyObject * | ||
| 3283 | 1609449 | type_new(PyTypeObject *metatype, PyObject *args, PyObject *kwds) | |
| 3284 | { | ||
| 3285 | assert(args != NULL && PyTuple_Check(args)); | ||
| 3286 | assert(kwds == NULL || PyDict_Check(kwds)); | ||
| 3287 | |||
| 3288 | /* Parse arguments: (name, bases, dict) */ | ||
| 3289 | PyObject *name, *bases, *orig_dict; | ||
| 3290 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 1609449 times.
|
1609449 | if (!PyArg_ParseTuple(args, "UO!O!:type.__new__", |
| 3291 | &name, | ||
| 3292 | &PyTuple_Type, &bases, | ||
| 3293 | &PyDict_Type, &orig_dict)) | ||
| 3294 | { | ||
| 3295 | ✗ | return NULL; | |
| 3296 | } | ||
| 3297 | |||
| 3298 | 1609449 | type_new_ctx ctx = { | |
| 3299 | .metatype = metatype, | ||
| 3300 | .args = args, | ||
| 3301 | .kwds = kwds, | ||
| 3302 | .orig_dict = orig_dict, | ||
| 3303 | .name = name, | ||
| 3304 | .bases = bases, | ||
| 3305 | .base = NULL, | ||
| 3306 | .slots = NULL, | ||
| 3307 | .nslot = 0, | ||
| 3308 | .add_dict = 0, | ||
| 3309 | .add_weak = 0, | ||
| 3310 | .may_add_dict = 0, | ||
| 3311 | .may_add_weak = 0}; | ||
| 3312 | 1609449 | PyObject *type = NULL; | |
| 3313 | 1609449 | int res = type_new_get_bases(&ctx, &type); | |
| 3314 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1609449 times.
|
1609449 | if (res < 0) { |
| 3315 | assert(PyErr_Occurred()); | ||
| 3316 | ✗ | return NULL; | |
| 3317 | } | ||
| 3318 |
2/2✓ Branch 0 taken 26696 times.
✓ Branch 1 taken 1582753 times.
|
1609449 | if (res == 1) { |
| 3319 | assert(type != NULL); | ||
| 3320 | 26696 | return type; | |
| 3321 | } | ||
| 3322 | assert(ctx.base != NULL); | ||
| 3323 | assert(ctx.bases != NULL); | ||
| 3324 | |||
| 3325 | 1582753 | type = type_new_impl(&ctx); | |
| 3326 | 1582753 | Py_DECREF(ctx.bases); | |
| 3327 | 1582753 | return type; | |
| 3328 | } | ||
| 3329 | |||
| 3330 | |||
| 3331 | static PyObject * | ||
| 3332 | 1580874 | type_vectorcall(PyObject *metatype, PyObject *const *args, | |
| 3333 | size_t nargsf, PyObject *kwnames) | ||
| 3334 | { | ||
| 3335 | 1580874 | Py_ssize_t nargs = PyVectorcall_NARGS(nargsf); | |
| 3336 |
3/4✓ Branch 0 taken 337643 times.
✓ Branch 1 taken 1243231 times.
✓ Branch 2 taken 337643 times.
✗ Branch 3 not taken.
|
1580874 | if (nargs == 1 && metatype == (PyObject *)&PyType_Type){ |
| 3337 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 337643 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
|
337643 | if (!_PyArg_NoKwnames("type", kwnames)) { |
| 3338 | ✗ | return NULL; | |
| 3339 | } | ||
| 3340 | 337643 | return Py_NewRef(Py_TYPE(args[0])); | |
| 3341 | } | ||
| 3342 | /* In other (much less common) cases, fall back to | ||
| 3343 | more flexible calling conventions. */ | ||
| 3344 | 1243231 | PyThreadState *tstate = _PyThreadState_GET(); | |
| 3345 | 1243231 | return _PyObject_MakeTpCall(tstate, metatype, args, nargs, kwnames); | |
| 3346 | } | ||
| 3347 | |||
| 3348 | /* An array of type slot offsets corresponding to Py_tp_* constants, | ||
| 3349 | * for use in e.g. PyType_Spec and PyType_GetSlot. | ||
| 3350 | * Each entry has two offsets: "slot_offset" and "subslot_offset". | ||
| 3351 | * If is subslot_offset is -1, slot_offset is an offset within the | ||
| 3352 | * PyTypeObject struct. | ||
| 3353 | * Otherwise slot_offset is an offset to a pointer to a sub-slots struct | ||
| 3354 | * (such as "tp_as_number"), and subslot_offset is the offset within | ||
| 3355 | * that struct. | ||
| 3356 | * The actual table is generated by a script. | ||
| 3357 | */ | ||
| 3358 | static const PySlot_Offset pyslot_offsets[] = { | ||
| 3359 | {0, 0}, | ||
| 3360 | #include "typeslots.inc" | ||
| 3361 | }; | ||
| 3362 | |||
| 3363 | /* Given a PyType_FromMetaclass `bases` argument (NULL, type, or tuple of | ||
| 3364 | * types), return a tuple of types. | ||
| 3365 | */ | ||
| 3366 | inline static PyObject * | ||
| 3367 | 127934 | get_bases_tuple(PyObject *bases_in, PyType_Spec *spec) | |
| 3368 | { | ||
| 3369 |
2/2✓ Branch 0 taken 88544 times.
✓ Branch 1 taken 39390 times.
|
127934 | if (!bases_in) { |
| 3370 | /* Default: look in the spec, fall back to (type,). */ | ||
| 3371 | 88544 | PyTypeObject *base = &PyBaseObject_Type; // borrowed ref | |
| 3372 | 88544 | PyObject *bases = NULL; // borrowed ref | |
| 3373 | const PyType_Slot *slot; | ||
| 3374 |
2/2✓ Branch 0 taken 608181 times.
✓ Branch 1 taken 88544 times.
|
696725 | for (slot = spec->slots; slot->slot; slot++) { |
| 3375 |
2/3✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 608178 times.
|
608181 | switch (slot->slot) { |
| 3376 | 3 | case Py_tp_base: | |
| 3377 | 3 | base = slot->pfunc; | |
| 3378 | 3 | break; | |
| 3379 | ✗ | case Py_tp_bases: | |
| 3380 | ✗ | bases = slot->pfunc; | |
| 3381 | ✗ | break; | |
| 3382 | } | ||
| 3383 | } | ||
| 3384 |
1/2✓ Branch 0 taken 88544 times.
✗ Branch 1 not taken.
|
88544 | if (!bases) { |
| 3385 | 88544 | return PyTuple_Pack(1, base); | |
| 3386 | } | ||
| 3387 | ✗ | if (PyTuple_Check(bases)) { | |
| 3388 | ✗ | return Py_NewRef(bases); | |
| 3389 | } | ||
| 3390 | ✗ | PyErr_SetString(PyExc_SystemError, "Py_tp_bases is not a tuple"); | |
| 3391 | ✗ | return NULL; | |
| 3392 | } | ||
| 3393 |
2/2✓ Branch 2 taken 318 times.
✓ Branch 3 taken 39072 times.
|
39390 | if (PyTuple_Check(bases_in)) { |
| 3394 | 318 | return Py_NewRef(bases_in); | |
| 3395 | } | ||
| 3396 | // Not a tuple, should be a single type | ||
| 3397 | 39072 | return PyTuple_Pack(1, bases_in); | |
| 3398 | } | ||
| 3399 | |||
| 3400 | static inline int | ||
| 3401 | 127934 | check_basicsize_includes_size_and_offsets(PyTypeObject* type) | |
| 3402 | { | ||
| 3403 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 127934 times.
|
127934 | if (type->tp_alloc != PyType_GenericAlloc) { |
| 3404 | // Custom allocators can ignore tp_basicsize | ||
| 3405 | ✗ | return 1; | |
| 3406 | } | ||
| 3407 | 127934 | Py_ssize_t max = (Py_ssize_t)type->tp_basicsize; | |
| 3408 | |||
| 3409 |
2/4✓ Branch 0 taken 127934 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 127934 times.
|
127934 | if (type->tp_base && type->tp_base->tp_basicsize > type->tp_basicsize) { |
| 3410 | ✗ | PyErr_Format(PyExc_TypeError, | |
| 3411 | "tp_basicsize for type '%s' (%d) is too small for base '%s' (%d)", | ||
| 3412 | type->tp_name, type->tp_basicsize, | ||
| 3413 | ✗ | type->tp_base->tp_name, type->tp_base->tp_basicsize); | |
| 3414 | ✗ | return 0; | |
| 3415 | } | ||
| 3416 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 127934 times.
|
127934 | if (type->tp_weaklistoffset + (Py_ssize_t)sizeof(PyObject*) > max) { |
| 3417 | ✗ | PyErr_Format(PyExc_TypeError, | |
| 3418 | "weaklist offset %d is out of bounds for type '%s' (tp_basicsize = %d)", | ||
| 3419 | type->tp_weaklistoffset, | ||
| 3420 | type->tp_name, type->tp_basicsize); | ||
| 3421 | ✗ | return 0; | |
| 3422 | } | ||
| 3423 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 127934 times.
|
127934 | if (type->tp_dictoffset + (Py_ssize_t)sizeof(PyObject*) > max) { |
| 3424 | ✗ | PyErr_Format(PyExc_TypeError, | |
| 3425 | "dict offset %d is out of bounds for type '%s' (tp_basicsize = %d)", | ||
| 3426 | type->tp_dictoffset, | ||
| 3427 | type->tp_name, type->tp_basicsize); | ||
| 3428 | ✗ | return 0; | |
| 3429 | } | ||
| 3430 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 127934 times.
|
127934 | if (type->tp_vectorcall_offset + (Py_ssize_t)sizeof(vectorcallfunc*) > max) { |
| 3431 | ✗ | PyErr_Format(PyExc_TypeError, | |
| 3432 | "vectorcall offset %d is out of bounds for type '%s' (tp_basicsize = %d)", | ||
| 3433 | type->tp_vectorcall_offset, | ||
| 3434 | type->tp_name, type->tp_basicsize); | ||
| 3435 | ✗ | return 0; | |
| 3436 | } | ||
| 3437 | 127934 | return 1; | |
| 3438 | } | ||
| 3439 | |||
| 3440 | PyObject * | ||
| 3441 | 127934 | PyType_FromMetaclass(PyTypeObject *metaclass, PyObject *module, | |
| 3442 | PyType_Spec *spec, PyObject *bases_in) | ||
| 3443 | { | ||
| 3444 | /* Invariant: A non-NULL value in one of these means this function holds | ||
| 3445 | * a strong reference or owns allocated memory. | ||
| 3446 | * These get decrefed/freed/returned at the end, on both success and error. | ||
| 3447 | */ | ||
| 3448 | 127934 | PyHeapTypeObject *res = NULL; | |
| 3449 | PyTypeObject *type; | ||
| 3450 | 127934 | PyObject *bases = NULL; | |
| 3451 | 127934 | char *tp_doc = NULL; | |
| 3452 | 127934 | PyObject *ht_name = NULL; | |
| 3453 | 127934 | char *_ht_tpname = NULL; | |
| 3454 | |||
| 3455 | int r; | ||
| 3456 | |||
| 3457 | /* Prepare slots that need special handling. | ||
| 3458 | * Keep in mind that a slot can be given multiple times: | ||
| 3459 | * if that would cause trouble (leaks, UB, ...), raise an exception. | ||
| 3460 | */ | ||
| 3461 | |||
| 3462 | const PyType_Slot *slot; | ||
| 3463 | 127934 | Py_ssize_t nmembers = 0; | |
| 3464 | Py_ssize_t weaklistoffset, dictoffset, vectorcalloffset; | ||
| 3465 | char *res_start; | ||
| 3466 | |||
| 3467 | 127934 | nmembers = weaklistoffset = dictoffset = vectorcalloffset = 0; | |
| 3468 |
2/2✓ Branch 0 taken 877927 times.
✓ Branch 1 taken 127934 times.
|
1005861 | for (slot = spec->slots; slot->slot; slot++) { |
| 3469 |
1/2✓ Branch 0 taken 877927 times.
✗ Branch 1 not taken.
|
877927 | if (slot->slot < 0 |
| 3470 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 877927 times.
|
877927 | || (size_t)slot->slot >= Py_ARRAY_LENGTH(pyslot_offsets)) { |
| 3471 | ✗ | PyErr_SetString(PyExc_RuntimeError, "invalid slot offset"); | |
| 3472 | ✗ | goto finally; | |
| 3473 | } | ||
| 3474 |
3/3✓ Branch 0 taken 95018 times.
✓ Branch 1 taken 92953 times.
✓ Branch 2 taken 689956 times.
|
877927 | switch (slot->slot) { |
| 3475 | 95018 | case Py_tp_members: | |
| 3476 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 95018 times.
|
95018 | if (nmembers != 0) { |
| 3477 | ✗ | PyErr_SetString( | |
| 3478 | PyExc_SystemError, | ||
| 3479 | "Multiple Py_tp_members slots are not supported."); | ||
| 3480 | ✗ | goto finally; | |
| 3481 | } | ||
| 3482 |
2/2✓ Branch 0 taken 402958 times.
✓ Branch 1 taken 95018 times.
|
497976 | for (const PyMemberDef *memb = slot->pfunc; memb->name != NULL; memb++) { |
| 3483 | 402958 | nmembers++; | |
| 3484 |
2/2✓ Branch 0 taken 25459 times.
✓ Branch 1 taken 377499 times.
|
402958 | if (strcmp(memb->name, "__weaklistoffset__") == 0) { |
| 3485 | // The PyMemberDef must be a Py_ssize_t and readonly | ||
| 3486 | assert(memb->type == T_PYSSIZET); | ||
| 3487 | assert(memb->flags == READONLY); | ||
| 3488 | 25459 | weaklistoffset = memb->offset; | |
| 3489 | } | ||
| 3490 |
2/2✓ Branch 0 taken 5711 times.
✓ Branch 1 taken 397247 times.
|
402958 | if (strcmp(memb->name, "__dictoffset__") == 0) { |
| 3491 | // The PyMemberDef must be a Py_ssize_t and readonly | ||
| 3492 | assert(memb->type == T_PYSSIZET); | ||
| 3493 | assert(memb->flags == READONLY); | ||
| 3494 | 5711 | dictoffset = memb->offset; | |
| 3495 | } | ||
| 3496 |
2/2✓ Branch 0 taken 7371 times.
✓ Branch 1 taken 395587 times.
|
402958 | if (strcmp(memb->name, "__vectorcalloffset__") == 0) { |
| 3497 | // The PyMemberDef must be a Py_ssize_t and readonly | ||
| 3498 | assert(memb->type == T_PYSSIZET); | ||
| 3499 | assert(memb->flags == READONLY); | ||
| 3500 | 7371 | vectorcalloffset = memb->offset; | |
| 3501 | } | ||
| 3502 | } | ||
| 3503 | 95018 | break; | |
| 3504 | 92953 | case Py_tp_doc: | |
| 3505 | /* For the docstring slot, which usually points to a static string | ||
| 3506 | literal, we need to make a copy */ | ||
| 3507 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 92953 times.
|
92953 | if (tp_doc != NULL) { |
| 3508 | ✗ | PyErr_SetString( | |
| 3509 | PyExc_SystemError, | ||
| 3510 | "Multiple Py_tp_doc slots are not supported."); | ||
| 3511 | ✗ | goto finally; | |
| 3512 | } | ||
| 3513 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 92950 times.
|
92953 | if (slot->pfunc == NULL) { |
| 3514 | 3 | PyObject_Free(tp_doc); | |
| 3515 | 3 | tp_doc = NULL; | |
| 3516 | } | ||
| 3517 | else { | ||
| 3518 | 92950 | size_t len = strlen(slot->pfunc)+1; | |
| 3519 | 92950 | tp_doc = PyObject_Malloc(len); | |
| 3520 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 92950 times.
|
92950 | if (tp_doc == NULL) { |
| 3521 | ✗ | PyErr_NoMemory(); | |
| 3522 | ✗ | goto finally; | |
| 3523 | } | ||
| 3524 | 92950 | memcpy(tp_doc, slot->pfunc, len); | |
| 3525 | } | ||
| 3526 | 92953 | break; | |
| 3527 | } | ||
| 3528 | } | ||
| 3529 | |||
| 3530 | /* Prepare the type name and qualname */ | ||
| 3531 | |||
| 3532 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 127934 times.
|
127934 | if (spec->name == NULL) { |
| 3533 | ✗ | PyErr_SetString(PyExc_SystemError, | |
| 3534 | "Type spec does not define the name field."); | ||
| 3535 | ✗ | goto finally; | |
| 3536 | } | ||
| 3537 | |||
| 3538 | 127934 | const char *s = strrchr(spec->name, '.'); | |
| 3539 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 127934 times.
|
127934 | if (s == NULL) { |
| 3540 | ✗ | s = spec->name; | |
| 3541 | } | ||
| 3542 | else { | ||
| 3543 | 127934 | s++; | |
| 3544 | } | ||
| 3545 | |||
| 3546 | 127934 | ht_name = PyUnicode_FromString(s); | |
| 3547 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 127934 times.
|
127934 | if (!ht_name) { |
| 3548 | ✗ | goto finally; | |
| 3549 | } | ||
| 3550 | |||
| 3551 | /* Copy spec->name to a buffer we own. | ||
| 3552 | * | ||
| 3553 | * Unfortunately, we can't use tp_name directly (with some | ||
| 3554 | * flag saying that it should be deallocated with the type), | ||
| 3555 | * because tp_name is public API and may be set independently | ||
| 3556 | * of any such flag. | ||
| 3557 | * So, we use a separate buffer, _ht_tpname, that's always | ||
| 3558 | * deallocated with the type (if it's non-NULL). | ||
| 3559 | */ | ||
| 3560 | 127934 | Py_ssize_t name_buf_len = strlen(spec->name) + 1; | |
| 3561 | 127934 | _ht_tpname = PyMem_Malloc(name_buf_len); | |
| 3562 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 127934 times.
|
127934 | if (_ht_tpname == NULL) { |
| 3563 | ✗ | goto finally; | |
| 3564 | } | ||
| 3565 | 127934 | memcpy(_ht_tpname, spec->name, name_buf_len); | |
| 3566 | |||
| 3567 | /* Get a tuple of bases. | ||
| 3568 | * bases is a strong reference (unlike bases_in). | ||
| 3569 | */ | ||
| 3570 | 127934 | bases = get_bases_tuple(bases_in, spec); | |
| 3571 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 127934 times.
|
127934 | if (!bases) { |
| 3572 | ✗ | goto finally; | |
| 3573 | } | ||
| 3574 | |||
| 3575 | /* Calculate the metaclass */ | ||
| 3576 | |||
| 3577 |
2/2✓ Branch 0 taken 127932 times.
✓ Branch 1 taken 2 times.
|
127934 | if (!metaclass) { |
| 3578 | 127932 | metaclass = &PyType_Type; | |
| 3579 | } | ||
| 3580 | 127934 | metaclass = _PyType_CalculateMetaclass(metaclass, bases); | |
| 3581 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 127934 times.
|
127934 | if (metaclass == NULL) { |
| 3582 | ✗ | goto finally; | |
| 3583 | } | ||
| 3584 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 127934 times.
|
127934 | if (!PyType_Check(metaclass)) { |
| 3585 | ✗ | PyErr_Format(PyExc_TypeError, | |
| 3586 | "Metaclass '%R' is not a subclass of 'type'.", | ||
| 3587 | metaclass); | ||
| 3588 | ✗ | goto finally; | |
| 3589 | } | ||
| 3590 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 127934 times.
|
127934 | if (metaclass->tp_new != PyType_Type.tp_new) { |
| 3591 | ✗ | PyErr_SetString(PyExc_TypeError, | |
| 3592 | "Metaclasses with custom tp_new are not supported."); | ||
| 3593 | ✗ | goto finally; | |
| 3594 | } | ||
| 3595 | |||
| 3596 | /* Calculate best base, and check that all bases are type objects */ | ||
| 3597 | 127934 | PyTypeObject *base = best_base(bases); // borrowed ref | |
| 3598 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 127934 times.
|
127934 | if (base == NULL) { |
| 3599 | ✗ | goto finally; | |
| 3600 | } | ||
| 3601 | // best_base should check Py_TPFLAGS_BASETYPE & raise a proper exception, | ||
| 3602 | // here we just check its work | ||
| 3603 | assert(_PyType_HasFeature(base, Py_TPFLAGS_BASETYPE)); | ||
| 3604 | |||
| 3605 | /* Allocate the new type | ||
| 3606 | * | ||
| 3607 | * Between here and PyType_Ready, we should limit: | ||
| 3608 | * - calls to Python code | ||
| 3609 | * - raising exceptions | ||
| 3610 | * - memory allocations | ||
| 3611 | */ | ||
| 3612 | |||
| 3613 | 127934 | res = (PyHeapTypeObject*)metaclass->tp_alloc(metaclass, nmembers); | |
| 3614 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 127934 times.
|
127934 | if (res == NULL) { |
| 3615 | ✗ | goto finally; | |
| 3616 | } | ||
| 3617 | 127934 | res_start = (char*)res; | |
| 3618 | |||
| 3619 | 127934 | type = &res->ht_type; | |
| 3620 | /* The flags must be initialized early, before the GC traverses us */ | ||
| 3621 | 127934 | type->tp_flags = spec->flags | Py_TPFLAGS_HEAPTYPE; | |
| 3622 | |||
| 3623 | 127934 | res->ht_module = Py_XNewRef(module); | |
| 3624 | |||
| 3625 | /* Initialize essential fields */ | ||
| 3626 | |||
| 3627 | 127934 | type->tp_as_async = &res->as_async; | |
| 3628 | 127934 | type->tp_as_number = &res->as_number; | |
| 3629 | 127934 | type->tp_as_sequence = &res->as_sequence; | |
| 3630 | 127934 | type->tp_as_mapping = &res->as_mapping; | |
| 3631 | 127934 | type->tp_as_buffer = &res->as_buffer; | |
| 3632 | |||
| 3633 | /* Set slots we have prepared */ | ||
| 3634 | |||
| 3635 | 127934 | type->tp_base = (PyTypeObject *)Py_NewRef(base); | |
| 3636 | 127934 | type->tp_bases = bases; | |
| 3637 | 127934 | bases = NULL; // We give our reference to bases to the type | |
| 3638 | |||
| 3639 | 127934 | type->tp_doc = tp_doc; | |
| 3640 | 127934 | tp_doc = NULL; // Give ownership of the allocated memory to the type | |
| 3641 | |||
| 3642 | 127934 | res->ht_qualname = Py_NewRef(ht_name); | |
| 3643 | 127934 | res->ht_name = ht_name; | |
| 3644 | 127934 | ht_name = NULL; // Give our reference to to the type | |
| 3645 | |||
| 3646 | 127934 | type->tp_name = _ht_tpname; | |
| 3647 | 127934 | res->_ht_tpname = _ht_tpname; | |
| 3648 | 127934 | _ht_tpname = NULL; // Give ownership to to the type | |
| 3649 | |||
| 3650 | /* Copy the sizes */ | ||
| 3651 | |||
| 3652 | 127934 | type->tp_basicsize = spec->basicsize; | |
| 3653 | 127934 | type->tp_itemsize = spec->itemsize; | |
| 3654 | |||
| 3655 | /* Copy all the ordinary slots */ | ||
| 3656 | |||
| 3657 |
2/2✓ Branch 0 taken 877927 times.
✓ Branch 1 taken 127934 times.
|
1005861 | for (slot = spec->slots; slot->slot; slot++) { |
| 3658 |
3/3✓ Branch 0 taken 92956 times.
✓ Branch 1 taken 95018 times.
✓ Branch 2 taken 689953 times.
|
877927 | switch (slot->slot) { |
| 3659 | 92956 | case Py_tp_base: | |
| 3660 | case Py_tp_bases: | ||
| 3661 | case Py_tp_doc: | ||
| 3662 | /* Processed above */ | ||
| 3663 | 92956 | break; | |
| 3664 | 95018 | case Py_tp_members: | |
| 3665 | { | ||
| 3666 | /* Move the slots to the heap type itself */ | ||
| 3667 | 95018 | size_t len = Py_TYPE(type)->tp_itemsize * nmembers; | |
| 3668 | 95018 | memcpy(_PyHeapType_GET_MEMBERS(res), slot->pfunc, len); | |
| 3669 | 95018 | type->tp_members = _PyHeapType_GET_MEMBERS(res); | |
| 3670 | } | ||
| 3671 | 95018 | break; | |
| 3672 | 689953 | default: | |
| 3673 | { | ||
| 3674 | /* Copy other slots directly */ | ||
| 3675 | 689953 | PySlot_Offset slotoffsets = pyslot_offsets[slot->slot]; | |
| 3676 | 689953 | short slot_offset = slotoffsets.slot_offset; | |
| 3677 |
2/2✓ Branch 0 taken 661190 times.
✓ Branch 1 taken 28763 times.
|
689953 | if (slotoffsets.subslot_offset == -1) { |
| 3678 | 661190 | *(void**)((char*)res_start + slot_offset) = slot->pfunc; | |
| 3679 | } | ||
| 3680 | else { | ||
| 3681 | 28763 | void *procs = *(void**)((char*)res_start + slot_offset); | |
| 3682 | 28763 | short subslot_offset = slotoffsets.subslot_offset; | |
| 3683 | 28763 | *(void**)((char*)procs + subslot_offset) = slot->pfunc; | |
| 3684 | } | ||
| 3685 | } | ||
| 3686 | 689953 | break; | |
| 3687 | } | ||
| 3688 | } | ||
| 3689 |
2/2✓ Branch 0 taken 2986 times.
✓ Branch 1 taken 124948 times.
|
127934 | if (type->tp_dealloc == NULL) { |
| 3690 | /* It's a heap type, so needs the heap types' dealloc. | ||
| 3691 | subtype_dealloc will call the base type's tp_dealloc, if | ||
| 3692 | necessary. */ | ||
| 3693 | 2986 | type->tp_dealloc = subtype_dealloc; | |
| 3694 | } | ||
| 3695 | |||
| 3696 | /* Set up offsets */ | ||
| 3697 | |||
| 3698 | 127934 | type->tp_vectorcall_offset = vectorcalloffset; | |
| 3699 | 127934 | type->tp_weaklistoffset = weaklistoffset; | |
| 3700 | 127934 | type->tp_dictoffset = dictoffset; | |
| 3701 | |||
| 3702 | /* Ready the type (which includes inheritance). | ||
| 3703 | * | ||
| 3704 | * After this call we should generally only touch up what's | ||
| 3705 | * accessible to Python code, like __dict__. | ||
| 3706 | */ | ||
| 3707 | |||
| 3708 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 127934 times.
|
127934 | if (PyType_Ready(type) < 0) { |
| 3709 | ✗ | goto finally; | |
| 3710 | } | ||
| 3711 | |||
| 3712 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 127934 times.
|
127934 | if (!check_basicsize_includes_size_and_offsets(type)) { |
| 3713 | ✗ | goto finally; | |
| 3714 | } | ||
| 3715 | |||
| 3716 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 127934 times.
|
127934 | if (type->tp_flags & Py_TPFLAGS_MANAGED_DICT) { |
| 3717 | ✗ | res->ht_cached_keys = _PyDict_NewKeysForClass(); | |
| 3718 | } | ||
| 3719 | |||
| 3720 |
2/2✓ Branch 0 taken 92950 times.
✓ Branch 1 taken 34984 times.
|
127934 | if (type->tp_doc) { |
| 3721 | 92950 | PyObject *__doc__ = PyUnicode_FromString(_PyType_DocWithoutSignature(type->tp_name, type->tp_doc)); | |
| 3722 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 92950 times.
|
92950 | if (!__doc__) { |
| 3723 | ✗ | goto finally; | |
| 3724 | } | ||
| 3725 | 92950 | r = PyDict_SetItem(type->tp_dict, &_Py_ID(__doc__), __doc__); | |
| 3726 | 92950 | Py_DECREF(__doc__); | |
| 3727 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 92950 times.
|
92950 | if (r < 0) { |
| 3728 | ✗ | goto finally; | |
| 3729 | } | ||
| 3730 | } | ||
| 3731 | |||
| 3732 |
2/2✓ Branch 0 taken 25459 times.
✓ Branch 1 taken 102475 times.
|
127934 | if (weaklistoffset) { |
| 3733 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 25459 times.
|
25459 | if (PyDict_DelItem((PyObject *)type->tp_dict, &_Py_ID(__weaklistoffset__)) < 0) { |
| 3734 | ✗ | goto finally; | |
| 3735 | } | ||
| 3736 | } | ||
| 3737 |
2/2✓ Branch 0 taken 5711 times.
✓ Branch 1 taken 122223 times.
|
127934 | if (dictoffset) { |
| 3738 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 5711 times.
|
5711 | if (PyDict_DelItem((PyObject *)type->tp_dict, &_Py_ID(__dictoffset__)) < 0) { |
| 3739 | ✗ | goto finally; | |
| 3740 | } | ||
| 3741 | } | ||
| 3742 | |||
| 3743 | /* Set type.__module__ */ | ||
| 3744 | 127934 | r = PyDict_Contains(type->tp_dict, &_Py_ID(__module__)); | |
| 3745 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 127934 times.
|
127934 | if (r < 0) { |
| 3746 | ✗ | goto finally; | |
| 3747 | } | ||
| 3748 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 127934 times.
|
127934 | if (r == 0) { |
| 3749 | 127934 | s = strrchr(spec->name, '.'); | |
| 3750 |
1/2✓ Branch 0 taken 127934 times.
✗ Branch 1 not taken.
|
127934 | if (s != NULL) { |
| 3751 | 127934 | PyObject *modname = PyUnicode_FromStringAndSize( | |
| 3752 | 127934 | spec->name, (Py_ssize_t)(s - spec->name)); | |
| 3753 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 127934 times.
|
127934 | if (modname == NULL) { |
| 3754 | ✗ | goto finally; | |
| 3755 | } | ||
| 3756 | 127934 | r = PyDict_SetItem(type->tp_dict, &_Py_ID(__module__), modname); | |
| 3757 | 127934 | Py_DECREF(modname); | |
| 3758 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 127934 times.
|
127934 | if (r != 0) { |
| 3759 | ✗ | goto finally; | |
| 3760 | } | ||
| 3761 | } | ||
| 3762 | else { | ||
| 3763 | ✗ | if (PyErr_WarnFormat(PyExc_DeprecationWarning, 1, | |
| 3764 | "builtin type %.200s has no __module__ attribute", | ||
| 3765 | spec->name)) | ||
| 3766 | ✗ | goto finally; | |
| 3767 | } | ||
| 3768 | } | ||
| 3769 | |||
| 3770 | assert(_PyType_CheckConsistency(type)); | ||
| 3771 | |||
| 3772 | ✗ | finally: | |
| 3773 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 127934 times.
|
127934 | if (PyErr_Occurred()) { |
| 3774 | ✗ | Py_CLEAR(res); | |
| 3775 | } | ||
| 3776 | 127934 | Py_XDECREF(bases); | |
| 3777 | 127934 | PyObject_Free(tp_doc); | |
| 3778 | 127934 | Py_XDECREF(ht_name); | |
| 3779 | 127934 | PyMem_Free(_ht_tpname); | |
| 3780 | 127934 | return (PyObject*)res; | |
| 3781 | } | ||
| 3782 | |||
| 3783 | PyObject * | ||
| 3784 | 72936 | PyType_FromModuleAndSpec(PyObject *module, PyType_Spec *spec, PyObject *bases) | |
| 3785 | { | ||
| 3786 | 72936 | return PyType_FromMetaclass(NULL, module, spec, bases); | |
| 3787 | } | ||
| 3788 | |||
| 3789 | PyObject * | ||
| 3790 | 39071 | PyType_FromSpecWithBases(PyType_Spec *spec, PyObject *bases) | |
| 3791 | { | ||
| 3792 | 39071 | return PyType_FromMetaclass(NULL, NULL, spec, bases); | |
| 3793 | } | ||
| 3794 | |||
| 3795 | PyObject * | ||
| 3796 | 15925 | PyType_FromSpec(PyType_Spec *spec) | |
| 3797 | { | ||
| 3798 | 15925 | return PyType_FromMetaclass(NULL, NULL, spec, NULL); | |
| 3799 | } | ||
| 3800 | |||
| 3801 | PyObject * | ||
| 3802 | ✗ | PyType_GetName(PyTypeObject *type) | |
| 3803 | { | ||
| 3804 | ✗ | return type_name(type, NULL); | |
| 3805 | } | ||
| 3806 | |||
| 3807 | PyObject * | ||
| 3808 | ✗ | PyType_GetQualName(PyTypeObject *type) | |
| 3809 | { | ||
| 3810 | ✗ | return type_qualname(type, NULL); | |
| 3811 | } | ||
| 3812 | |||
| 3813 | void * | ||
| 3814 | 919695 | PyType_GetSlot(PyTypeObject *type, int slot) | |
| 3815 | { | ||
| 3816 | void *parent_slot; | ||
| 3817 | 919695 | int slots_len = Py_ARRAY_LENGTH(pyslot_offsets); | |
| 3818 | |||
| 3819 |
2/4✓ Branch 0 taken 919695 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 919695 times.
|
919695 | if (slot <= 0 || slot >= slots_len) { |
| 3820 | ✗ | PyErr_BadInternalCall(); | |
| 3821 | ✗ | return NULL; | |
| 3822 | } | ||
| 3823 | |||
| 3824 | 919695 | parent_slot = *(void**)((char*)type + pyslot_offsets[slot].slot_offset); | |
| 3825 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 919695 times.
|
919695 | if (parent_slot == NULL) { |
| 3826 | ✗ | return NULL; | |
| 3827 | } | ||
| 3828 | /* Return slot directly if we have no sub slot. */ | ||
| 3829 |
1/2✓ Branch 0 taken 919695 times.
✗ Branch 1 not taken.
|
919695 | if (pyslot_offsets[slot].subslot_offset == -1) { |
| 3830 | 919695 | return parent_slot; | |
| 3831 | } | ||
| 3832 | ✗ | return *(void**)((char*)parent_slot + pyslot_offsets[slot].subslot_offset); | |
| 3833 | } | ||
| 3834 | |||
| 3835 | PyObject * | ||
| 3836 | 13101660 | PyType_GetModule(PyTypeObject *type) | |
| 3837 | { | ||
| 3838 | assert(PyType_Check(type)); | ||
| 3839 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 13101660 times.
|
13101660 | if (!_PyType_HasFeature(type, Py_TPFLAGS_HEAPTYPE)) { |
| 3840 | ✗ | PyErr_Format( | |
| 3841 | PyExc_TypeError, | ||
| 3842 | "PyType_GetModule: Type '%s' is not a heap type", | ||
| 3843 | type->tp_name); | ||
| 3844 | ✗ | return NULL; | |
| 3845 | } | ||
| 3846 | |||
| 3847 | 13101660 | PyHeapTypeObject* et = (PyHeapTypeObject*)type; | |
| 3848 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 13101660 times.
|
13101660 | if (!et->ht_module) { |
| 3849 | ✗ | PyErr_Format( | |
| 3850 | PyExc_TypeError, | ||
| 3851 | "PyType_GetModule: Type '%s' has no associated module", | ||
| 3852 | type->tp_name); | ||
| 3853 | ✗ | return NULL; | |
| 3854 | } | ||
| 3855 | 13101660 | return et->ht_module; | |
| 3856 | |||
| 3857 | } | ||
| 3858 | |||
| 3859 | void * | ||
| 3860 | 326239 | PyType_GetModuleState(PyTypeObject *type) | |
| 3861 | { | ||
| 3862 | 326239 | PyObject *m = PyType_GetModule(type); | |
| 3863 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 326239 times.
|
326239 | if (m == NULL) { |
| 3864 | ✗ | return NULL; | |
| 3865 | } | ||
| 3866 | 326239 | return _PyModule_GetState(m); | |
| 3867 | } | ||
| 3868 | |||
| 3869 | |||
| 3870 | /* Get the module of the first superclass where the module has the | ||
| 3871 | * given PyModuleDef. | ||
| 3872 | */ | ||
| 3873 | PyObject * | ||
| 3874 | 722169320 | PyType_GetModuleByDef(PyTypeObject *type, PyModuleDef *def) | |
| 3875 | { | ||
| 3876 | assert(PyType_Check(type)); | ||
| 3877 | |||
| 3878 | 722169320 | PyObject *mro = type->tp_mro; | |
| 3879 | // The type must be ready | ||
| 3880 | assert(mro != NULL); | ||
| 3881 | assert(PyTuple_Check(mro)); | ||
| 3882 | // mro_invoke() ensures that the type MRO cannot be empty, so we don't have | ||
| 3883 | // to check i < PyTuple_GET_SIZE(mro) at the first loop iteration. | ||
| 3884 | assert(PyTuple_GET_SIZE(mro) >= 1); | ||
| 3885 | |||
| 3886 | 722169320 | Py_ssize_t n = PyTuple_GET_SIZE(mro); | |
| 3887 |
1/2✓ Branch 0 taken 726507291 times.
✗ Branch 1 not taken.
|
726507291 | for (Py_ssize_t i = 0; i < n; i++) { |
| 3888 | 726507291 | PyObject *super = PyTuple_GET_ITEM(mro, i); | |
| 3889 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 726507291 times.
|
726507291 | if(!_PyType_HasFeature((PyTypeObject *)super, Py_TPFLAGS_HEAPTYPE)) { |
| 3890 | // Static types in the MRO need to be skipped | ||
| 3891 | ✗ | continue; | |
| 3892 | } | ||
| 3893 | |||
| 3894 | 726507291 | PyHeapTypeObject *ht = (PyHeapTypeObject*)super; | |
| 3895 | 726507291 | PyObject *module = ht->ht_module; | |
| 3896 |
3/4✓ Branch 0 taken 722169320 times.
✓ Branch 1 taken 4337971 times.
✓ Branch 3 taken 722169320 times.
✗ Branch 4 not taken.
|
726507291 | if (module && _PyModule_GetDef(module) == def) { |
| 3897 | 722169320 | return module; | |
| 3898 | } | ||
| 3899 | } | ||
| 3900 | |||
| 3901 | ✗ | PyErr_Format( | |
| 3902 | PyExc_TypeError, | ||
| 3903 | "PyType_GetModuleByDef: No superclass of '%s' has the given module", | ||
| 3904 | type->tp_name); | ||
| 3905 | ✗ | return NULL; | |
| 3906 | } | ||
| 3907 | |||
| 3908 | |||
| 3909 | /* Internal API to look for a name through the MRO, bypassing the method cache. | ||
| 3910 | This returns a borrowed reference, and might set an exception. | ||
| 3911 | 'error' is set to: -1: error with exception; 1: error without exception; 0: ok */ | ||
| 3912 | static PyObject * | ||
| 3913 | 210301589 | find_name_in_mro(PyTypeObject *type, PyObject *name, int *error) | |
| 3914 | { | ||
| 3915 | Py_hash_t hash; | ||
| 3916 |
1/2✓ Branch 1 taken 210301589 times.
✗ Branch 2 not taken.
|
210301589 | if (!PyUnicode_CheckExact(name) || |
| 3917 |
2/2✓ Branch 0 taken 9698988 times.
✓ Branch 1 taken 200602601 times.
|
210301589 | (hash = _PyASCIIObject_CAST(name)->hash) == -1) |
| 3918 | { | ||
| 3919 | 9698988 | hash = PyObject_Hash(name); | |
| 3920 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 9698988 times.
|
9698988 | if (hash == -1) { |
| 3921 | ✗ | *error = -1; | |
| 3922 | ✗ | return NULL; | |
| 3923 | } | ||
| 3924 | } | ||
| 3925 | |||
| 3926 | /* Look in tp_dict of types in MRO */ | ||
| 3927 | 210301589 | PyObject *mro = type->tp_mro; | |
| 3928 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 210301589 times.
|
210301589 | if (mro == NULL) { |
| 3929 | ✗ | if ((type->tp_flags & Py_TPFLAGS_READYING) == 0) { | |
| 3930 | ✗ | if (PyType_Ready(type) < 0) { | |
| 3931 | ✗ | *error = -1; | |
| 3932 | ✗ | return NULL; | |
| 3933 | } | ||
| 3934 | ✗ | mro = type->tp_mro; | |
| 3935 | } | ||
| 3936 | ✗ | if (mro == NULL) { | |
| 3937 | ✗ | *error = 1; | |
| 3938 | ✗ | return NULL; | |
| 3939 | } | ||
| 3940 | } | ||
| 3941 | |||
| 3942 | 210301589 | PyObject *res = NULL; | |
| 3943 | /* Keep a strong reference to mro because type->tp_mro can be replaced | ||
| 3944 | during dict lookup, e.g. when comparing to non-string keys. */ | ||
| 3945 | 210301589 | Py_INCREF(mro); | |
| 3946 | 210301589 | Py_ssize_t n = PyTuple_GET_SIZE(mro); | |
| 3947 |
2/2✓ Branch 0 taken 728113022 times.
✓ Branch 1 taken 139890286 times.
|
868003308 | for (Py_ssize_t i = 0; i < n; i++) { |
| 3948 | 728113022 | PyObject *base = PyTuple_GET_ITEM(mro, i); | |
| 3949 | 728113022 | PyObject *dict = _PyType_CAST(base)->tp_dict; | |
| 3950 | assert(dict && PyDict_Check(dict)); | ||
| 3951 | 728113022 | res = _PyDict_GetItem_KnownHash(dict, name, hash); | |
| 3952 |
2/2✓ Branch 0 taken 70411303 times.
✓ Branch 1 taken 657701719 times.
|
728113022 | if (res != NULL) { |
| 3953 | 70411303 | break; | |
| 3954 | } | ||
| 3955 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 657701719 times.
|
657701719 | if (PyErr_Occurred()) { |
| 3956 | ✗ | *error = -1; | |
| 3957 | ✗ | goto done; | |
| 3958 | } | ||
| 3959 | } | ||
| 3960 | 210301589 | *error = 0; | |
| 3961 | 210301589 | done: | |
| 3962 | 210301589 | Py_DECREF(mro); | |
| 3963 | 210301589 | return res; | |
| 3964 | } | ||
| 3965 | |||
| 3966 | /* Internal API to look for a name through the MRO. | ||
| 3967 | This returns a borrowed reference, and doesn't set an exception! */ | ||
| 3968 | PyObject * | ||
| 3969 | 3699232369 | _PyType_Lookup(PyTypeObject *type, PyObject *name) | |
| 3970 | { | ||
| 3971 | PyObject *res; | ||
| 3972 | int error; | ||
| 3973 | |||
| 3974 | 3699232369 | unsigned int h = MCACHE_HASH_METHOD(type, name); | |
| 3975 | 3699232369 | struct type_cache *cache = get_type_cache(); | |
| 3976 | 3699232369 | struct type_cache_entry *entry = &cache->hashtable[h]; | |
| 3977 |
2/2✓ Branch 0 taken 3651396323 times.
✓ Branch 1 taken 47836046 times.
|
3699232369 | if (entry->version == type->tp_version_tag && |
| 3978 |
2/2✓ Branch 0 taken 3635830488 times.
✓ Branch 1 taken 15565835 times.
|
3651396323 | entry->name == name) { |
| 3979 | #if MCACHE_STATS | ||
| 3980 | cache->hits++; | ||
| 3981 | #endif | ||
| 3982 | assert(_PyType_HasFeature(type, Py_TPFLAGS_VALID_VERSION_TAG)); | ||
| 3983 | 3635830488 | return entry->value; | |
| 3984 | } | ||
| 3985 | |||
| 3986 | /* We may end up clearing live exceptions below, so make sure it's ours. */ | ||
| 3987 | assert(!PyErr_Occurred()); | ||
| 3988 | |||
| 3989 | 63401881 | res = find_name_in_mro(type, name, &error); | |
| 3990 | /* Only put NULL results into cache if there was no error. */ | ||
| 3991 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 63401881 times.
|
63401881 | if (error) { |
| 3992 | /* It's not ideal to clear the error condition, | ||
| 3993 | but this function is documented as not setting | ||
| 3994 | an exception, and I don't want to change that. | ||
| 3995 | E.g., when PyType_Ready() can't proceed, it won't | ||
| 3996 | set the "ready" flag, so future attempts to ready | ||
| 3997 | the same type will call it again -- hopefully | ||
| 3998 | in a context that propagates the exception out. | ||
| 3999 | */ | ||
| 4000 | ✗ | if (error == -1) { | |
| 4001 | ✗ | PyErr_Clear(); | |
| 4002 | } | ||
| 4003 | ✗ | return NULL; | |
| 4004 | } | ||
| 4005 | |||
| 4006 |
4/8✓ Branch 1 taken 63401881 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 63401881 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 63401881 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 63401881 times.
✗ Branch 11 not taken.
|
63401881 | if (MCACHE_CACHEABLE_NAME(name) && assign_version_tag(cache, type)) { |
| 4007 | 63401881 | h = MCACHE_HASH_METHOD(type, name); | |
| 4008 | 63401881 | struct type_cache_entry *entry = &cache->hashtable[h]; | |
| 4009 | 63401881 | entry->version = type->tp_version_tag; | |
| 4010 | 63401881 | entry->value = res; /* borrowed */ | |
| 4011 | assert(_PyASCIIObject_CAST(name)->hash != -1); | ||
| 4012 | #if MCACHE_STATS | ||
| 4013 | if (entry->name != Py_None && entry->name != name) { | ||
| 4014 | cache->collisions++; | ||
| 4015 | } | ||
| 4016 | else { | ||
| 4017 | cache->misses++; | ||
| 4018 | } | ||
| 4019 | #endif | ||
| 4020 | assert(_PyType_HasFeature(type, Py_TPFLAGS_VALID_VERSION_TAG)); | ||
| 4021 | 63401881 | Py_SETREF(entry->name, Py_NewRef(name)); | |
| 4022 | } | ||
| 4023 | 63401881 | return res; | |
| 4024 | } | ||
| 4025 | |||
| 4026 | PyObject * | ||
| 4027 | ✗ | _PyType_LookupId(PyTypeObject *type, _Py_Identifier *name) | |
| 4028 | { | ||
| 4029 | PyObject *oname; | ||
| 4030 | ✗ | oname = _PyUnicode_FromId(name); /* borrowed */ | |
| 4031 | ✗ | if (oname == NULL) | |
| 4032 | ✗ | return NULL; | |
| 4033 | ✗ | return _PyType_Lookup(type, oname); | |
| 4034 | } | ||
| 4035 | |||
| 4036 | /* Check if the "readied" PyUnicode name | ||
| 4037 | is a double-underscore special name. */ | ||
| 4038 | static int | ||
| 4039 | 2307640 | is_dunder_name(PyObject *name) | |
| 4040 | { | ||
| 4041 | 2307640 | Py_ssize_t length = PyUnicode_GET_LENGTH(name); | |
| 4042 | 2307640 | int kind = PyUnicode_KIND(name); | |
| 4043 | /* Special names contain at least "__x__" and are always ASCII. */ | ||
| 4044 |
4/4✓ Branch 0 taken 2212647 times.
✓ Branch 1 taken 94993 times.
✓ Branch 2 taken 2211212 times.
✓ Branch 3 taken 1435 times.
|
2307640 | if (length > 4 && kind == PyUnicode_1BYTE_KIND) { |
| 4045 | 2211212 | const Py_UCS1 *characters = PyUnicode_1BYTE_DATA(name); | |
| 4046 | return ( | ||
| 4047 |
4/4✓ Branch 0 taken 788180 times.
✓ Branch 1 taken 1423032 times.
✓ Branch 2 taken 784757 times.
✓ Branch 3 taken 3423 times.
|
2995969 | ((characters[length-2] == '_') && (characters[length-1] == '_')) && |
| 4048 |
2/4✓ Branch 0 taken 784757 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 784757 times.
✗ Branch 3 not taken.
|
784757 | ((characters[0] == '_') && (characters[1] == '_')) |
| 4049 | ); | ||
| 4050 | } | ||
| 4051 | 96428 | return 0; | |
| 4052 | } | ||
| 4053 | |||
| 4054 | /* This is similar to PyObject_GenericGetAttr(), | ||
| 4055 | but uses _PyType_Lookup() instead of just looking in type->tp_dict. */ | ||
| 4056 | static PyObject * | ||
| 4057 | 190889102 | type_getattro(PyTypeObject *type, PyObject *name) | |
| 4058 | { | ||
| 4059 | 190889102 | PyTypeObject *metatype = Py_TYPE(type); | |
| 4060 | PyObject *meta_attribute, *attribute; | ||
| 4061 | descrgetfunc meta_get; | ||
| 4062 | PyObject* res; | ||
| 4063 | |||
| 4064 |
1/2✗ Branch 2 not taken.
✓ Branch 3 taken 190889102 times.
|
190889102 | if (!PyUnicode_Check(name)) { |
| 4065 | ✗ | PyErr_Format(PyExc_TypeError, | |
| 4066 | "attribute name must be string, not '%.200s'", | ||
| 4067 | ✗ | Py_TYPE(name)->tp_name); | |
| 4068 | ✗ | return NULL; | |
| 4069 | } | ||
| 4070 | |||
| 4071 | /* Initialize this type (we'll assume the metatype is initialized) */ | ||
| 4072 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 190889102 times.
|
190889102 | if (!_PyType_IsReady(type)) { |
| 4073 | ✗ | if (PyType_Ready(type) < 0) | |
| 4074 | ✗ | return NULL; | |
| 4075 | } | ||
| 4076 | |||
| 4077 | /* No readable descriptor found yet */ | ||
| 4078 | 190889102 | meta_get = NULL; | |
| 4079 | |||
| 4080 | /* Look for the attribute in the metatype */ | ||
| 4081 | 190889102 | meta_attribute = _PyType_Lookup(metatype, name); | |
| 4082 | |||
| 4083 |
2/2✓ Branch 0 taken 119500640 times.
✓ Branch 1 taken 71388462 times.
|
190889102 | if (meta_attribute != NULL) { |
| 4084 | 119500640 | Py_INCREF(meta_attribute); | |
| 4085 | 119500640 | meta_get = Py_TYPE(meta_attribute)->tp_descr_get; | |
| 4086 | |||
| 4087 |
4/4✓ Branch 0 taken 98883321 times.
✓ Branch 1 taken 20617319 times.
✓ Branch 3 taken 40396669 times.
✓ Branch 4 taken 58486652 times.
|
119500640 | if (meta_get != NULL && PyDescr_IsData(meta_attribute)) { |
| 4088 | /* Data descriptors implement tp_descr_set to intercept | ||
| 4089 | * writes. Assume the attribute is not overridden in | ||
| 4090 | * type's tp_dict (and bases): call the descriptor now. | ||
| 4091 | */ | ||
| 4092 | 40396669 | res = meta_get(meta_attribute, (PyObject *)type, | |
| 4093 | (PyObject *)metatype); | ||
| 4094 | 40396669 | Py_DECREF(meta_attribute); | |
| 4095 | 40396669 | return res; | |
| 4096 | } | ||
| 4097 | } | ||
| 4098 | |||
| 4099 | /* No data descriptor found on metatype. Look in tp_dict of this | ||
| 4100 | * type and its bases */ | ||
| 4101 | 150492433 | attribute = _PyType_Lookup(type, name); | |
| 4102 |
2/2✓ Branch 0 taken 115730017 times.
✓ Branch 1 taken 34762416 times.
|
150492433 | if (attribute != NULL) { |
| 4103 | /* Implement descriptor functionality, if any */ | ||
| 4104 | 115730017 | Py_INCREF(attribute); | |
| 4105 | 115730017 | descrgetfunc local_get = Py_TYPE(attribute)->tp_descr_get; | |
| 4106 | |||
| 4107 | 115730017 | Py_XDECREF(meta_attribute); | |
| 4108 | |||
| 4109 |
2/2✓ Branch 0 taken 98679964 times.
✓ Branch 1 taken 17050053 times.
|
115730017 | if (local_get != NULL) { |
| 4110 | /* NULL 2nd argument indicates the descriptor was | ||
| 4111 | * found on the target object itself (or a base) */ | ||
| 4112 | 98679964 | res = local_get(attribute, (PyObject *)NULL, | |
| 4113 | (PyObject *)type); | ||
| 4114 | 98679964 | Py_DECREF(attribute); | |
| 4115 | 98679964 | return res; | |
| 4116 | } | ||
| 4117 | |||
| 4118 | 17050053 | return attribute; | |
| 4119 | } | ||
| 4120 | |||
| 4121 | /* No attribute found in local __dict__ (or bases): use the | ||
| 4122 | * descriptor from the metatype, if any */ | ||
| 4123 |
2/2✓ Branch 0 taken 14103653 times.
✓ Branch 1 taken 20658763 times.
|
34762416 | if (meta_get != NULL) { |
| 4124 | PyObject *res; | ||
| 4125 | 14103653 | res = meta_get(meta_attribute, (PyObject *)type, | |
| 4126 | (PyObject *)metatype); | ||
| 4127 | 14103653 | Py_DECREF(meta_attribute); | |
| 4128 | 14103653 | return res; | |
| 4129 | } | ||
| 4130 | |||
| 4131 | /* If an ordinary attribute was found on the metatype, return it now */ | ||
| 4132 |
2/2✓ Branch 0 taken 176 times.
✓ Branch 1 taken 20658587 times.
|
20658763 | if (meta_attribute != NULL) { |
| 4133 | 176 | return meta_attribute; | |
| 4134 | } | ||
| 4135 | |||
| 4136 | /* Give up */ | ||
| 4137 | 20658587 | PyErr_Format(PyExc_AttributeError, | |
| 4138 | "type object '%.50s' has no attribute '%U'", | ||
| 4139 | type->tp_name, name); | ||
| 4140 | 20658587 | return NULL; | |
| 4141 | } | ||
| 4142 | |||
| 4143 | static int | ||
| 4144 | 2307640 | type_setattro(PyTypeObject *type, PyObject *name, PyObject *value) | |
| 4145 | { | ||
| 4146 | int res; | ||
| 4147 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2307640 times.
|
2307640 | if (type->tp_flags & Py_TPFLAGS_IMMUTABLETYPE) { |
| 4148 | ✗ | PyErr_Format( | |
| 4149 | PyExc_TypeError, | ||
| 4150 | "cannot set %R attribute of immutable type '%s'", | ||
| 4151 | name, type->tp_name); | ||
| 4152 | ✗ | return -1; | |
| 4153 | } | ||
| 4154 |
1/2✓ Branch 2 taken 2307640 times.
✗ Branch 3 not taken.
|
2307640 | if (PyUnicode_Check(name)) { |
| 4155 |
1/2✓ Branch 1 taken 2307640 times.
✗ Branch 2 not taken.
|
2307640 | if (PyUnicode_CheckExact(name)) { |
| 4156 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 2307640 times.
|
2307640 | if (PyUnicode_READY(name) == -1) |
| 4157 | ✗ | return -1; | |
| 4158 | 2307640 | Py_INCREF(name); | |
| 4159 | } | ||
| 4160 | else { | ||
| 4161 | ✗ | name = _PyUnicode_Copy(name); | |
| 4162 | ✗ | if (name == NULL) | |
| 4163 | ✗ | return -1; | |
| 4164 | } | ||
| 4165 | /* bpo-40521: Interned strings are shared by all subinterpreters */ | ||
| 4166 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 2307640 times.
|
2307640 | if (!PyUnicode_CHECK_INTERNED(name)) { |
| 4167 | ✗ | PyUnicode_InternInPlace(&name); | |
| 4168 | ✗ | if (!PyUnicode_CHECK_INTERNED(name)) { | |
| 4169 | ✗ | PyErr_SetString(PyExc_MemoryError, | |
| 4170 | "Out of memory interning an attribute name"); | ||
| 4171 | ✗ | Py_DECREF(name); | |
| 4172 | ✗ | return -1; | |
| 4173 | } | ||
| 4174 | } | ||
| 4175 | } | ||
| 4176 | else { | ||
| 4177 | /* Will fail in _PyObject_GenericSetAttrWithDict. */ | ||
| 4178 | ✗ | Py_INCREF(name); | |
| 4179 | } | ||
| 4180 | 2307640 | res = _PyObject_GenericSetAttrWithDict((PyObject *)type, name, value, NULL); | |
| 4181 |
1/2✓ Branch 0 taken 2307640 times.
✗ Branch 1 not taken.
|
2307640 | if (res == 0) { |
| 4182 | /* Clear the VALID_VERSION flag of 'type' and all its | ||
| 4183 | subclasses. This could possibly be unified with the | ||
| 4184 | update_subclasses() recursion in update_slot(), but carefully: | ||
| 4185 | they each have their own conditions on which to stop | ||
| 4186 | recursing into subclasses. */ | ||
| 4187 | 2307640 | PyType_Modified(type); | |
| 4188 | |||
| 4189 |
2/2✓ Branch 1 taken 784757 times.
✓ Branch 2 taken 1522883 times.
|
2307640 | if (is_dunder_name(name)) { |
| 4190 | 784757 | res = update_slot(type, name); | |
| 4191 | } | ||
| 4192 | assert(_PyType_CheckConsistency(type)); | ||
| 4193 | } | ||
| 4194 | 2307640 | Py_DECREF(name); | |
| 4195 | 2307640 | return res; | |
| 4196 | } | ||
| 4197 | |||
| 4198 | extern void | ||
| 4199 | _PyDictKeys_DecRef(PyDictKeysObject *keys); | ||
| 4200 | |||
| 4201 | |||
| 4202 | static void | ||
| 4203 | 2246998 | type_dealloc_common(PyTypeObject *type) | |
| 4204 | { | ||
| 4205 |
1/2✓ Branch 0 taken 2246998 times.
✗ Branch 1 not taken.
|
2246998 | if (type->tp_bases != NULL) { |
| 4206 | PyObject *tp, *val, *tb; | ||
| 4207 | 2246998 | PyErr_Fetch(&tp, &val, &tb); | |
| 4208 | 2246998 | remove_all_subclasses(type, type->tp_bases); | |
| 4209 | 2246998 | PyErr_Restore(tp, val, tb); | |
| 4210 | } | ||
| 4211 | 2246998 | } | |
| 4212 | |||
| 4213 | |||
| 4214 | void | ||
| 4215 | 677396 | _PyStaticType_Dealloc(PyTypeObject *type) | |
| 4216 | { | ||
| 4217 | // If a type still has subtypes, it cannot be deallocated. | ||
| 4218 | // A subtype can inherit attributes and methods of its parent type, | ||
| 4219 | // and a type must no longer be used once it's deallocated. | ||
| 4220 |
2/2✓ Branch 0 taken 23498 times.
✓ Branch 1 taken 653898 times.
|
677396 | if (type->tp_subclasses != NULL) { |
| 4221 | 23498 | return; | |
| 4222 | } | ||
| 4223 | |||
| 4224 | 653898 | type_dealloc_common(type); | |
| 4225 | |||
| 4226 |
1/2✓ Branch 0 taken 653898 times.
✗ Branch 1 not taken.
|
653898 | Py_CLEAR(type->tp_dict); |
| 4227 |
1/2✓ Branch 0 taken 653898 times.
✗ Branch 1 not taken.
|
653898 | Py_CLEAR(type->tp_bases); |
| 4228 |
1/2✓ Branch 0 taken 653898 times.
✗ Branch 1 not taken.
|
653898 | Py_CLEAR(type->tp_mro); |
| 4229 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 653898 times.
|
653898 | Py_CLEAR(type->tp_cache); |
| 4230 | // type->tp_subclasses is NULL | ||
| 4231 | |||
| 4232 | // PyObject_ClearWeakRefs() raises an exception if Py_REFCNT() != 0 | ||
| 4233 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 653898 times.
|
653898 | if (Py_REFCNT(type) == 0) { |
| 4234 | ✗ | PyObject_ClearWeakRefs((PyObject *)type); | |
| 4235 | } | ||
| 4236 | |||
| 4237 | 653898 | type->tp_flags &= ~Py_TPFLAGS_READY; | |
| 4238 | } | ||
| 4239 | |||
| 4240 | |||
| 4241 | static void | ||
| 4242 | 1593100 | type_dealloc(PyTypeObject *type) | |
| 4243 | { | ||
| 4244 | // Assert this is a heap-allocated type object | ||
| 4245 | _PyObject_ASSERT((PyObject *)type, type->tp_flags & Py_TPFLAGS_HEAPTYPE); | ||
| 4246 | |||
| 4247 | 1593100 | _PyObject_GC_UNTRACK(type); | |
| 4248 | |||
| 4249 | 1593100 | type_dealloc_common(type); | |
| 4250 | |||
| 4251 | // PyObject_ClearWeakRefs() raises an exception if Py_REFCNT() != 0 | ||
| 4252 | assert(Py_REFCNT(type) == 0); | ||
| 4253 | 1593100 | PyObject_ClearWeakRefs((PyObject *)type); | |
| 4254 | |||
| 4255 | 1593100 | Py_XDECREF(type->tp_base); | |
| 4256 | 1593100 | Py_XDECREF(type->tp_dict); | |
| 4257 | 1593100 | Py_XDECREF(type->tp_bases); | |
| 4258 | 1593100 | Py_XDECREF(type->tp_mro); | |
| 4259 | 1593100 | Py_XDECREF(type->tp_cache); | |
| 4260 | 1593100 | Py_XDECREF(type->tp_subclasses); | |
| 4261 | |||
| 4262 | /* A type's tp_doc is heap allocated, unlike the tp_doc slots | ||
| 4263 | * of most other objects. It's okay to cast it to char *. | ||
| 4264 | */ | ||
| 4265 | 1593100 | PyObject_Free((char *)type->tp_doc); | |
| 4266 | |||
| 4267 | 1593100 | PyHeapTypeObject *et = (PyHeapTypeObject *)type; | |
| 4268 | 1593100 | Py_XDECREF(et->ht_name); | |
| 4269 | 1593100 | Py_XDECREF(et->ht_qualname); | |
| 4270 | 1593100 | Py_XDECREF(et->ht_slots); | |
| 4271 |
2/2✓ Branch 0 taken 850505 times.
✓ Branch 1 taken 742595 times.
|
1593100 | if (et->ht_cached_keys) { |
| 4272 | 850505 | _PyDictKeys_DecRef(et->ht_cached_keys); | |
| 4273 | } | ||
| 4274 | 1593100 | Py_XDECREF(et->ht_module); | |
| 4275 | 1593100 | PyMem_Free(et->_ht_tpname); | |
| 4276 | 1593100 | Py_TYPE(type)->tp_free((PyObject *)type); | |
| 4277 | 1593100 | } | |
| 4278 | |||
| 4279 | |||
| 4280 | PyObject* | ||
| 4281 | 566750 | _PyType_GetSubclasses(PyTypeObject *self) | |
| 4282 | { | ||
| 4283 | 566750 | PyObject *list = PyList_New(0); | |
| 4284 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 566750 times.
|
566750 | if (list == NULL) { |
| 4285 | ✗ | return NULL; | |
| 4286 | } | ||
| 4287 | |||
| 4288 | 566750 | PyObject *subclasses = self->tp_subclasses; // borrowed ref | |
| 4289 |
2/2✓ Branch 0 taken 453222 times.
✓ Branch 1 taken 113528 times.
|
566750 | if (subclasses == NULL) { |
| 4290 | 453222 | return list; | |
| 4291 | } | ||
| 4292 | assert(PyDict_CheckExact(subclasses)); | ||
| 4293 | // The loop cannot modify tp_subclasses, there is no need | ||
| 4294 | // to hold a strong reference (use a borrowed reference). | ||
| 4295 | |||
| 4296 | 113528 | Py_ssize_t i = 0; | |
| 4297 | PyObject *ref; // borrowed ref | ||
| 4298 |
2/2✓ Branch 1 taken 447409 times.
✓ Branch 2 taken 113528 times.
|
560937 | while (PyDict_Next(subclasses, &i, NULL, &ref)) { |
| 4299 | assert(PyWeakref_CheckRef(ref)); | ||
| 4300 | 447409 | PyObject *obj = PyWeakref_GET_OBJECT(ref); // borrowed ref | |
| 4301 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 447409 times.
|
447409 | if (obj == Py_None) { |
| 4302 | ✗ | continue; | |
| 4303 | } | ||
| 4304 | assert(PyType_Check(obj)); | ||
| 4305 | |||
| 4306 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 447409 times.
|
447409 | if (PyList_Append(list, obj) < 0) { |
| 4307 | ✗ | Py_DECREF(list); | |
| 4308 | ✗ | return NULL; | |
| 4309 | } | ||
| 4310 | } | ||
| 4311 | 113528 | return list; | |
| 4312 | } | ||
| 4313 | |||
| 4314 | |||
| 4315 | /*[clinic input] | ||
| 4316 | type.__subclasses__ | ||
| 4317 | |||
| 4318 | Return a list of immediate subclasses. | ||
| 4319 | [clinic start generated code]*/ | ||
| 4320 | |||
| 4321 | static PyObject * | ||
| 4322 | 566176 | type___subclasses___impl(PyTypeObject *self) | |
| 4323 | /*[clinic end generated code: output=eb5eb54485942819 input=5af66132436f9a7b]*/ | ||
| 4324 | { | ||
| 4325 | 566176 | return _PyType_GetSubclasses(self); | |
| 4326 | } | ||
| 4327 | |||
| 4328 | static PyObject * | ||
| 4329 | 1258641 | type_prepare(PyObject *self, PyObject *const *args, Py_ssize_t nargs, | |
| 4330 | PyObject *kwnames) | ||
| 4331 | { | ||
| 4332 | 1258641 | return PyDict_New(); | |
| 4333 | } | ||
| 4334 | |||
| 4335 | |||
| 4336 | /* | ||
| 4337 | Merge the __dict__ of aclass into dict, and recursively also all | ||
| 4338 | the __dict__s of aclass's base classes. The order of merging isn't | ||
| 4339 | defined, as it's expected that only the final set of dict keys is | ||
| 4340 | interesting. | ||
| 4341 | Return 0 on success, -1 on error. | ||
| 4342 | */ | ||
| 4343 | |||
| 4344 | static int | ||
| 4345 | 32550 | merge_class_dict(PyObject *dict, PyObject *aclass) | |
| 4346 | { | ||
| 4347 | PyObject *classdict; | ||
| 4348 | PyObject *bases; | ||
| 4349 | |||
| 4350 | assert(PyDict_Check(dict)); | ||
| 4351 | assert(aclass); | ||
| 4352 | |||
| 4353 | /* Merge in the type's dict (if any). */ | ||
| 4354 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 32550 times.
|
32550 | if (_PyObject_LookupAttr(aclass, &_Py_ID(__dict__), &classdict) < 0) { |
| 4355 | ✗ | return -1; | |
| 4356 | } | ||
| 4357 |
1/2✓ Branch 0 taken 32550 times.
✗ Branch 1 not taken.
|
32550 | if (classdict != NULL) { |
| 4358 | 32550 | int status = PyDict_Update(dict, classdict); | |
| 4359 | 32550 | Py_DECREF(classdict); | |
| 4360 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 32550 times.
|
32550 | if (status < 0) |
| 4361 | ✗ | return -1; | |
| 4362 | } | ||
| 4363 | |||
| 4364 | /* Recursively merge in the base types' (if any) dicts. */ | ||
| 4365 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 32550 times.
|
32550 | if (_PyObject_LookupAttr(aclass, &_Py_ID(__bases__), &bases) < 0) { |
| 4366 | ✗ | return -1; | |
| 4367 | } | ||
| 4368 |
1/2✓ Branch 0 taken 32550 times.
✗ Branch 1 not taken.
|
32550 | if (bases != NULL) { |
| 4369 | /* We have no guarantee that bases is a real tuple */ | ||
| 4370 | Py_ssize_t i, n; | ||
| 4371 | 32550 | n = PySequence_Size(bases); /* This better be right */ | |
| 4372 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 32550 times.
|
32550 | if (n < 0) { |
| 4373 | ✗ | Py_DECREF(bases); | |
| 4374 | ✗ | return -1; | |
| 4375 | } | ||
| 4376 | else { | ||
| 4377 |
2/2✓ Branch 0 taken 27288 times.
✓ Branch 1 taken 32550 times.
|
59838 | for (i = 0; i < n; i++) { |
| 4378 | int status; | ||
| 4379 | 27288 | PyObject *base = PySequence_GetItem(bases, i); | |
| 4380 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 27288 times.
|
27288 | if (base == NULL) { |
| 4381 | ✗ | Py_DECREF(bases); | |
| 4382 | ✗ | return -1; | |
| 4383 | } | ||
| 4384 | 27288 | status = merge_class_dict(dict, base); | |
| 4385 | 27288 | Py_DECREF(base); | |
| 4386 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 27288 times.
|
27288 | if (status < 0) { |
| 4387 | ✗ | Py_DECREF(bases); | |
| 4388 | ✗ | return -1; | |
| 4389 | } | ||
| 4390 | } | ||
| 4391 | } | ||
| 4392 | 32550 | Py_DECREF(bases); | |
| 4393 | } | ||
| 4394 | 32550 | return 0; | |
| 4395 | } | ||
| 4396 | |||
| 4397 | /* __dir__ for type objects: returns __dict__ and __bases__. | ||
| 4398 | We deliberately don't suck up its __class__, as methods belonging to the | ||
| 4399 | metaclass would probably be more confusing than helpful. | ||
| 4400 | */ | ||
| 4401 | /*[clinic input] | ||
| 4402 | type.__dir__ | ||
| 4403 | |||
| 4404 | Specialized __dir__ implementation for types. | ||
| 4405 | [clinic start generated code]*/ | ||
| 4406 | |||
| 4407 | static PyObject * | ||
| 4408 | 1635 | type___dir___impl(PyTypeObject *self) | |
| 4409 | /*[clinic end generated code: output=69d02fe92c0f15fa input=7733befbec645968]*/ | ||
| 4410 | { | ||
| 4411 | 1635 | PyObject *result = NULL; | |
| 4412 | 1635 | PyObject *dict = PyDict_New(); | |
| 4413 | |||
| 4414 |
2/4✓ Branch 0 taken 1635 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 1635 times.
✗ Branch 4 not taken.
|
1635 | if (dict != NULL && merge_class_dict(dict, (PyObject *)self) == 0) |
| 4415 | 1635 | result = PyDict_Keys(dict); | |
| 4416 | |||
| 4417 | 1635 | Py_XDECREF(dict); | |
| 4418 | 1635 | return result; | |
| 4419 | } | ||
| 4420 | |||
| 4421 | /*[clinic input] | ||
| 4422 | type.__sizeof__ | ||
| 4423 | |||
| 4424 | Return memory consumption of the type object. | ||
| 4425 | [clinic start generated code]*/ | ||
| 4426 | |||
| 4427 | static PyObject * | ||
| 4428 | ✗ | type___sizeof___impl(PyTypeObject *self) | |
| 4429 | /*[clinic end generated code: output=766f4f16cd3b1854 input=99398f24b9cf45d6]*/ | ||
| 4430 | { | ||
| 4431 | Py_ssize_t size; | ||
| 4432 | ✗ | if (self->tp_flags & Py_TPFLAGS_HEAPTYPE) { | |
| 4433 | ✗ | PyHeapTypeObject* et = (PyHeapTypeObject*)self; | |
| 4434 | ✗ | size = sizeof(PyHeapTypeObject); | |
| 4435 | ✗ | if (et->ht_cached_keys) | |
| 4436 | ✗ | size += _PyDict_KeysSize(et->ht_cached_keys); | |
| 4437 | } | ||
| 4438 | else | ||
| 4439 | ✗ | size = sizeof(PyTypeObject); | |
| 4440 | ✗ | return PyLong_FromSsize_t(size); | |
| 4441 | } | ||
| 4442 | |||
| 4443 | static PyMethodDef type_methods[] = { | ||
| 4444 | TYPE_MRO_METHODDEF | ||
| 4445 | TYPE___SUBCLASSES___METHODDEF | ||
| 4446 | {"__prepare__", _PyCFunction_CAST(type_prepare), | ||
| 4447 | METH_FASTCALL | METH_KEYWORDS | METH_CLASS, | ||
| 4448 | PyDoc_STR("__prepare__() -> dict\n" | ||
| 4449 | "used to create the namespace for the class statement")}, | ||
| 4450 | TYPE___INSTANCECHECK___METHODDEF | ||
| 4451 | TYPE___SUBCLASSCHECK___METHODDEF | ||
| 4452 | TYPE___DIR___METHODDEF | ||
| 4453 | TYPE___SIZEOF___METHODDEF | ||
| 4454 | {0} | ||
| 4455 | }; | ||
| 4456 | |||
| 4457 | PyDoc_STRVAR(type_doc, | ||
| 4458 | "type(object) -> the object's type\n" | ||
| 4459 | "type(name, bases, dict, **kwds) -> a new type"); | ||
| 4460 | |||
| 4461 | static int | ||
| 4462 | 20771088 | type_traverse(PyTypeObject *type, visitproc visit, void *arg) | |
| 4463 | { | ||
| 4464 | /* Because of type_is_gc(), the collector only calls this | ||
| 4465 | for heaptypes. */ | ||
| 4466 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 20771088 times.
|
20771088 | if (!(type->tp_flags & Py_TPFLAGS_HEAPTYPE)) { |
| 4467 | char msg[200]; | ||
| 4468 | ✗ | sprintf(msg, "type_traverse() called on non-heap type '%.100s'", | |
| 4469 | type->tp_name); | ||
| 4470 | ✗ | _PyObject_ASSERT_FAILED_MSG((PyObject *)type, msg); | |
| 4471 | } | ||
| 4472 | |||
| 4473 |
3/4✓ Branch 0 taken 20770878 times.
✓ Branch 1 taken 210 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 20770878 times.
|
20771088 | Py_VISIT(type->tp_dict); |
| 4474 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 20771088 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
|
20771088 | Py_VISIT(type->tp_cache); |
| 4475 |
3/4✓ Branch 0 taken 20768382 times.
✓ Branch 1 taken 2706 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 20768382 times.
|
20771088 | Py_VISIT(type->tp_mro); |
| 4476 |
2/4✓ Branch 0 taken 20771088 times.
✗ Branch 1 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 20771088 times.
|
20771088 | Py_VISIT(type->tp_bases); |
| 4477 |
2/4✓ Branch 0 taken 20771088 times.
✗ Branch 1 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 20771088 times.
|
20771088 | Py_VISIT(type->tp_base); |
| 4478 |
3/4✓ Branch 0 taken 922130 times.
✓ Branch 1 taken 19848958 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 922130 times.
|
20771088 | Py_VISIT(((PyHeapTypeObject *)type)->ht_module); |
| 4479 | |||
| 4480 | /* There's no need to visit others because they can't be involved | ||
| 4481 | in cycles: | ||
| 4482 | type->tp_subclasses is a list of weak references, | ||
| 4483 | ((PyHeapTypeObject *)type)->ht_slots is a tuple of strings, | ||
| 4484 | ((PyHeapTypeObject *)type)->ht_*name are strings. | ||
| 4485 | */ | ||
| 4486 | |||
| 4487 | 20771088 | return 0; | |
| 4488 | } | ||
| 4489 | |||
| 4490 | static int | ||
| 4491 | 1593100 | type_clear(PyTypeObject *type) | |
| 4492 | { | ||
| 4493 | /* Because of type_is_gc(), the collector only calls this | ||
| 4494 | for heaptypes. */ | ||
| 4495 | _PyObject_ASSERT((PyObject *)type, type->tp_flags & Py_TPFLAGS_HEAPTYPE); | ||
| 4496 | |||
| 4497 | /* We need to invalidate the method cache carefully before clearing | ||
| 4498 | the dict, so that other objects caught in a reference cycle | ||
| 4499 | don't start calling destroyed methods. | ||
| 4500 | |||
| 4501 | Otherwise, the we need to clear tp_mro, which is | ||
| 4502 | part of a hard cycle (its first element is the class itself) that | ||
| 4503 | won't be broken otherwise (it's a tuple and tuples don't have a | ||
| 4504 | tp_clear handler). | ||
| 4505 | We also need to clear ht_module, if present: the module usually holds a | ||
| 4506 | reference to its class. None of the other fields need to be | ||
| 4507 | |||
| 4508 | cleared, and here's why: | ||
| 4509 | |||
| 4510 | tp_cache: | ||
| 4511 | Not used; if it were, it would be a dict. | ||
| 4512 | |||
| 4513 | tp_bases, tp_base: | ||
| 4514 | If these are involved in a cycle, there must be at least | ||
| 4515 | one other, mutable object in the cycle, e.g. a base | ||
| 4516 | class's dict; the cycle will be broken that way. | ||
| 4517 | |||
| 4518 | tp_subclasses: | ||
| 4519 | A dict of weak references can't be part of a cycle; and | ||
| 4520 | dicts have their own tp_clear. | ||
| 4521 | |||
| 4522 | slots (in PyHeapTypeObject): | ||
| 4523 | A tuple of strings can't be part of a cycle. | ||
| 4524 | */ | ||
| 4525 | |||
| 4526 | 1593100 | PyType_Modified(type); | |
| 4527 |
1/2✓ Branch 0 taken 1593100 times.
✗ Branch 1 not taken.
|
1593100 | if (type->tp_dict) { |
| 4528 | 1593100 | PyDict_Clear(type->tp_dict); | |
| 4529 | } | ||
| 4530 |
2/2✓ Branch 0 taken 63355 times.
✓ Branch 1 taken 1529745 times.
|
1593100 | Py_CLEAR(((PyHeapTypeObject *)type)->ht_module); |
| 4531 | |||
| 4532 |
1/2✓ Branch 0 taken 1593100 times.
✗ Branch 1 not taken.
|
1593100 | Py_CLEAR(type->tp_mro); |
| 4533 | |||
| 4534 | 1593100 | return 0; | |
| 4535 | } | ||
| 4536 | |||
| 4537 | static int | ||
| 4538 | 815780499 | type_is_gc(PyTypeObject *type) | |
| 4539 | { | ||
| 4540 | 815780499 | return type->tp_flags & Py_TPFLAGS_HEAPTYPE; | |
| 4541 | } | ||
| 4542 | |||
| 4543 | |||
| 4544 | static PyNumberMethods type_as_number = { | ||
| 4545 | .nb_or = _Py_union_type_or, // Add __or__ function | ||
| 4546 | }; | ||
| 4547 | |||
| 4548 | PyTypeObject PyType_Type = { | ||
| 4549 | PyVarObject_HEAD_INIT(&PyType_Type, 0) | ||
| 4550 | "type", /* tp_name */ | ||
| 4551 | sizeof(PyHeapTypeObject), /* tp_basicsize */ | ||
| 4552 | sizeof(PyMemberDef), /* tp_itemsize */ | ||
| 4553 | (destructor)type_dealloc, /* tp_dealloc */ | ||
| 4554 | offsetof(PyTypeObject, tp_vectorcall), /* tp_vectorcall_offset */ | ||
| 4555 | 0, /* tp_getattr */ | ||
| 4556 | 0, /* tp_setattr */ | ||
| 4557 | 0, /* tp_as_async */ | ||
| 4558 | (reprfunc)type_repr, /* tp_repr */ | ||
| 4559 | &type_as_number, /* tp_as_number */ | ||
| 4560 | 0, /* tp_as_sequence */ | ||
| 4561 | 0, /* tp_as_mapping */ | ||
| 4562 | 0, /* tp_hash */ | ||
| 4563 | (ternaryfunc)type_call, /* tp_call */ | ||
| 4564 | 0, /* tp_str */ | ||
| 4565 | (getattrofunc)type_getattro, /* tp_getattro */ | ||
| 4566 | (setattrofunc)type_setattro, /* tp_setattro */ | ||
| 4567 | 0, /* tp_as_buffer */ | ||
| 4568 | Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | | ||
| 4569 | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_TYPE_SUBCLASS | | ||
| 4570 | Py_TPFLAGS_HAVE_VECTORCALL, /* tp_flags */ | ||
| 4571 | type_doc, /* tp_doc */ | ||
| 4572 | (traverseproc)type_traverse, /* tp_traverse */ | ||
| 4573 | (inquiry)type_clear, /* tp_clear */ | ||
| 4574 | 0, /* tp_richcompare */ | ||
| 4575 | offsetof(PyTypeObject, tp_weaklist), /* tp_weaklistoffset */ | ||
| 4576 | 0, /* tp_iter */ | ||
| 4577 | 0, /* tp_iternext */ | ||
| 4578 | type_methods, /* tp_methods */ | ||
| 4579 | type_members, /* tp_members */ | ||
| 4580 | type_getsets, /* tp_getset */ | ||
| 4581 | 0, /* tp_base */ | ||
| 4582 | 0, /* tp_dict */ | ||
| 4583 | 0, /* tp_descr_get */ | ||
| 4584 | 0, /* tp_descr_set */ | ||
| 4585 | offsetof(PyTypeObject, tp_dict), /* tp_dictoffset */ | ||
| 4586 | type_init, /* tp_init */ | ||
| 4587 | 0, /* tp_alloc */ | ||
| 4588 | type_new, /* tp_new */ | ||
| 4589 | PyObject_GC_Del, /* tp_free */ | ||
| 4590 | (inquiry)type_is_gc, /* tp_is_gc */ | ||
| 4591 | .tp_vectorcall = type_vectorcall, | ||
| 4592 | }; | ||
| 4593 | |||
| 4594 | |||
| 4595 | /* The base type of all types (eventually)... except itself. */ | ||
| 4596 | |||
| 4597 | /* You may wonder why object.__new__() only complains about arguments | ||
| 4598 | when object.__init__() is not overridden, and vice versa. | ||
| 4599 | |||
| 4600 | Consider the use cases: | ||
| 4601 | |||
| 4602 | 1. When neither is overridden, we want to hear complaints about | ||
| 4603 | excess (i.e., any) arguments, since their presence could | ||
| 4604 | indicate there's a bug. | ||
| 4605 | |||
| 4606 | 2. When defining an Immutable type, we are likely to override only | ||
| 4607 | __new__(), since __init__() is called too late to initialize an | ||
| 4608 | Immutable object. Since __new__() defines the signature for the | ||
| 4609 | type, it would be a pain to have to override __init__() just to | ||
| 4610 | stop it from complaining about excess arguments. | ||
| 4611 | |||
| 4612 | 3. When defining a Mutable type, we are likely to override only | ||
| 4613 | __init__(). So here the converse reasoning applies: we don't | ||
| 4614 | want to have to override __new__() just to stop it from | ||
| 4615 | complaining. | ||
| 4616 | |||
| 4617 | 4. When __init__() is overridden, and the subclass __init__() calls | ||
| 4618 | object.__init__(), the latter should complain about excess | ||
| 4619 | arguments; ditto for __new__(). | ||
| 4620 | |||
| 4621 | Use cases 2 and 3 make it unattractive to unconditionally check for | ||
| 4622 | excess arguments. The best solution that addresses all four use | ||
| 4623 | cases is as follows: __init__() complains about excess arguments | ||
| 4624 | unless __new__() is overridden and __init__() is not overridden | ||
| 4625 | (IOW, if __init__() is overridden or __new__() is not overridden); | ||
| 4626 | symmetrically, __new__() complains about excess arguments unless | ||
| 4627 | __init__() is overridden and __new__() is not overridden | ||
| 4628 | (IOW, if __new__() is overridden or __init__() is not overridden). | ||
| 4629 | |||
| 4630 | However, for backwards compatibility, this breaks too much code. | ||
| 4631 | Therefore, in 2.6, we'll *warn* about excess arguments when both | ||
| 4632 | methods are overridden; for all other cases we'll use the above | ||
| 4633 | rules. | ||
| 4634 | |||
| 4635 | */ | ||
| 4636 | |||
| 4637 | /* Forward */ | ||
| 4638 | static PyObject * | ||
| 4639 | object_new(PyTypeObject *type, PyObject *args, PyObject *kwds); | ||
| 4640 | |||
| 4641 | static int | ||
| 4642 | 273742023 | excess_args(PyObject *args, PyObject *kwds) | |
| 4643 | { | ||
| 4644 |
4/4✓ Branch 1 taken 63948466 times.
✓ Branch 2 taken 209793557 times.
✓ Branch 3 taken 600670 times.
✓ Branch 4 taken 63347796 times.
|
274342693 | return PyTuple_GET_SIZE(args) || |
| 4645 |
3/4✓ Branch 2 taken 600670 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 574391 times.
✓ Branch 6 taken 26279 times.
|
600670 | (kwds && PyDict_Check(kwds) && PyDict_GET_SIZE(kwds)); |
| 4646 | } | ||
| 4647 | |||
| 4648 | static int | ||
| 4649 | 86276910 | object_init(PyObject *self, PyObject *args, PyObject *kwds) | |
| 4650 | { | ||
| 4651 | 86276910 | PyTypeObject *type = Py_TYPE(self); | |
| 4652 |
2/2✓ Branch 1 taken 76091539 times.
✓ Branch 2 taken 10185371 times.
|
86276910 | if (excess_args(args, kwds)) { |
| 4653 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 76091539 times.
|
76091539 | if (type->tp_init != object_init) { |
| 4654 | ✗ | PyErr_SetString(PyExc_TypeError, | |
| 4655 | "object.__init__() takes exactly one argument (the instance to initialize)"); | ||
| 4656 | ✗ | return -1; | |
| 4657 | } | ||
| 4658 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 76091539 times.
|
76091539 | if (type->tp_new == object_new) { |
| 4659 | ✗ | PyErr_Format(PyExc_TypeError, | |
| 4660 | "%.200s.__init__() takes exactly one argument (the instance to initialize)", | ||
| 4661 | type->tp_name); | ||
| 4662 | ✗ | return -1; | |
| 4663 | } | ||
| 4664 | } | ||
| 4665 | 86276910 | return 0; | |
| 4666 | } | ||
| 4667 | |||
| 4668 | static PyObject * | ||
| 4669 | 187465113 | object_new(PyTypeObject *type, PyObject *args, PyObject *kwds) | |
| 4670 | { | ||
| 4671 |
2/2✓ Branch 1 taken 134276409 times.
✓ Branch 2 taken 53188704 times.
|
187465113 | if (excess_args(args, kwds)) { |
| 4672 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 134276409 times.
|
134276409 | if (type->tp_new != object_new) { |
| 4673 | ✗ | PyErr_SetString(PyExc_TypeError, | |
| 4674 | "object.__new__() takes exactly one argument (the type to instantiate)"); | ||
| 4675 | ✗ | return NULL; | |
| 4676 | } | ||
| 4677 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 134276409 times.
|
134276409 | if (type->tp_init == object_init) { |
| 4678 | ✗ | PyErr_Format(PyExc_TypeError, "%.200s() takes no arguments", | |
| 4679 | type->tp_name); | ||
| 4680 | ✗ | return NULL; | |
| 4681 | } | ||
| 4682 | } | ||
| 4683 | |||
| 4684 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 187465113 times.
|
187465113 | if (type->tp_flags & Py_TPFLAGS_IS_ABSTRACT) { |
| 4685 | PyObject *abstract_methods; | ||
| 4686 | PyObject *sorted_methods; | ||
| 4687 | PyObject *joined; | ||
| 4688 | Py_ssize_t method_count; | ||
| 4689 | |||
| 4690 | /* Compute ", ".join(sorted(type.__abstractmethods__)) | ||
| 4691 | into joined. */ | ||
| 4692 | ✗ | abstract_methods = type_abstractmethods(type, NULL); | |
| 4693 | ✗ | if (abstract_methods == NULL) | |
| 4694 | ✗ | return NULL; | |
| 4695 | ✗ | sorted_methods = PySequence_List(abstract_methods); | |
| 4696 | ✗ | Py_DECREF(abstract_methods); | |
| 4697 | ✗ | if (sorted_methods == NULL) | |
| 4698 | ✗ | return NULL; | |
| 4699 | ✗ | if (PyList_Sort(sorted_methods)) { | |
| 4700 | ✗ | Py_DECREF(sorted_methods); | |
| 4701 | ✗ | return NULL; | |
| 4702 | } | ||
| 4703 | _Py_DECLARE_STR(comma_sep, ", "); | ||
| 4704 | ✗ | joined = PyUnicode_Join(&_Py_STR(comma_sep), sorted_methods); | |
| 4705 | ✗ | method_count = PyObject_Length(sorted_methods); | |
| 4706 | ✗ | Py_DECREF(sorted_methods); | |
| 4707 | ✗ | if (joined == NULL) | |
| 4708 | ✗ | return NULL; | |
| 4709 | ✗ | if (method_count == -1) | |
| 4710 | ✗ | return NULL; | |
| 4711 | |||
| 4712 | ✗ | PyErr_Format(PyExc_TypeError, | |
| 4713 | "Can't instantiate abstract class %s " | ||
| 4714 | "without an implementation for abstract method%s %U", | ||
| 4715 | type->tp_name, | ||
| 4716 | method_count > 1 ? "s" : "", | ||
| 4717 | joined); | ||
| 4718 | ✗ | Py_DECREF(joined); | |
| 4719 | ✗ | return NULL; | |
| 4720 | } | ||
| 4721 | 187465113 | PyObject *obj = type->tp_alloc(type, 0); | |
| 4722 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 187465113 times.
|
187465113 | if (obj == NULL) { |
| 4723 | ✗ | return NULL; | |
| 4724 | } | ||
| 4725 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 187465113 times.
|
187465113 | if (_PyObject_InitializeDict(obj)) { |
| 4726 | ✗ | Py_DECREF(obj); | |
| 4727 | ✗ | return NULL; | |
| 4728 | } | ||
| 4729 | 187465113 | return obj; | |
| 4730 | } | ||
| 4731 | |||
| 4732 | static void | ||
| 4733 | 1571978392 | object_dealloc(PyObject *self) | |
| 4734 | { | ||
| 4735 | 1571978392 | Py_TYPE(self)->tp_free(self); | |
| 4736 | 1571978392 | } | |
| 4737 | |||
| 4738 | static PyObject * | ||
| 4739 | 760 | object_repr(PyObject *self) | |
| 4740 | { | ||
| 4741 | PyTypeObject *type; | ||
| 4742 | PyObject *mod, *name, *rtn; | ||
| 4743 | |||
| 4744 | 760 | type = Py_TYPE(self); | |
| 4745 | 760 | mod = type_module(type, NULL); | |
| 4746 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 760 times.
|
760 | if (mod == NULL) |
| 4747 | ✗ | PyErr_Clear(); | |
| 4748 |
1/2✗ Branch 2 not taken.
✓ Branch 3 taken 760 times.
|
760 | else if (!PyUnicode_Check(mod)) { |
| 4749 | ✗ | Py_DECREF(mod); | |
| 4750 | ✗ | mod = NULL; | |
| 4751 | } | ||
| 4752 | 760 | name = type_qualname(type, NULL); | |
| 4753 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 760 times.
|
760 | if (name == NULL) { |
| 4754 | ✗ | Py_XDECREF(mod); | |
| 4755 | ✗ | return NULL; | |
| 4756 | } | ||
| 4757 |
2/4✓ Branch 0 taken 760 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 760 times.
✗ Branch 4 not taken.
|
760 | if (mod != NULL && !_PyUnicode_Equal(mod, &_Py_ID(builtins))) |
| 4758 | 760 | rtn = PyUnicode_FromFormat("<%U.%U object at %p>", mod, name, self); | |
| 4759 | else | ||
| 4760 | ✗ | rtn = PyUnicode_FromFormat("<%s object at %p>", | |
| 4761 | type->tp_name, self); | ||
| 4762 | 760 | Py_XDECREF(mod); | |
| 4763 | 760 | Py_DECREF(name); | |
| 4764 | 760 | return rtn; | |
| 4765 | } | ||
| 4766 | |||
| 4767 | static PyObject * | ||
| 4768 | 9159165 | object_str(PyObject *self) | |
| 4769 | { | ||
| 4770 | unaryfunc f; | ||
| 4771 | |||
| 4772 | 9159165 | f = Py_TYPE(self)->tp_repr; | |
| 4773 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 9159165 times.
|
9159165 | if (f == NULL) |
| 4774 | ✗ | f = object_repr; | |
| 4775 | 9159165 | return f(self); | |
| 4776 | } | ||
| 4777 | |||
| 4778 | static PyObject * | ||
| 4779 | 78999306 | object_richcompare(PyObject *self, PyObject *other, int op) | |
| 4780 | { | ||
| 4781 | PyObject *res; | ||
| 4782 | |||
| 4783 |
2/3✓ Branch 0 taken 71194092 times.
✓ Branch 1 taken 7805214 times.
✗ Branch 2 not taken.
|
78999306 | switch (op) { |
| 4784 | |||
| 4785 | 71194092 | case Py_EQ: | |
| 4786 | /* Return NotImplemented instead of False, so if two | ||
| 4787 | objects are compared, both get a chance at the | ||
| 4788 | comparison. See issue #1393. */ | ||
| 4789 |
2/2✓ Branch 0 taken 9292493 times.
✓ Branch 1 taken 61901599 times.
|
71194092 | res = (self == other) ? Py_True : Py_NotImplemented; |
| 4790 | 71194092 | Py_INCREF(res); | |
| 4791 | 71194092 | break; | |
| 4792 | |||
| 4793 | 7805214 | case Py_NE: | |
| 4794 | /* By default, __ne__() delegates to __eq__() and inverts the result, | ||
| 4795 | unless the latter returns NotImplemented. */ | ||
| 4796 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 7805214 times.
|
7805214 | if (Py_TYPE(self)->tp_richcompare == NULL) { |
| 4797 | ✗ | res = Py_NotImplemented; | |
| 4798 | ✗ | Py_INCREF(res); | |
| 4799 | ✗ | break; | |
| 4800 | } | ||
| 4801 | 7805214 | res = (*Py_TYPE(self)->tp_richcompare)(self, other, Py_EQ); | |
| 4802 |
3/4✓ Branch 0 taken 7805214 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5595984 times.
✓ Branch 3 taken 2209230 times.
|
7805214 | if (res != NULL && res != Py_NotImplemented) { |
| 4803 | 5595984 | int ok = PyObject_IsTrue(res); | |
| 4804 | 5595984 | Py_DECREF(res); | |
| 4805 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5595984 times.
|
5595984 | if (ok < 0) |
| 4806 | ✗ | res = NULL; | |
| 4807 | else { | ||
| 4808 |
2/2✓ Branch 0 taken 5595868 times.
✓ Branch 1 taken 116 times.
|
5595984 | if (ok) |
| 4809 | 5595868 | res = Py_False; | |
| 4810 | else | ||
| 4811 | 116 | res = Py_True; | |
| 4812 | 5595984 | Py_INCREF(res); | |
| 4813 | } | ||
| 4814 | } | ||
| 4815 | 7805214 | break; | |
| 4816 | |||
| 4817 | ✗ | default: | |
| 4818 | ✗ | res = Py_NotImplemented; | |
| 4819 | ✗ | Py_INCREF(res); | |
| 4820 | ✗ | break; | |
| 4821 | } | ||
| 4822 | |||
| 4823 | 78999306 | return res; | |
| 4824 | } | ||
| 4825 | |||
| 4826 | static PyObject * | ||
| 4827 | 274156621 | object_get_class(PyObject *self, void *closure) | |
| 4828 | { | ||
| 4829 | 274156621 | Py_INCREF(Py_TYPE(self)); | |
| 4830 | 274156621 | return (PyObject *)(Py_TYPE(self)); | |
| 4831 | } | ||
| 4832 | |||
| 4833 | static int | ||
| 4834 | 97706 | compatible_with_tp_base(PyTypeObject *child) | |
| 4835 | { | ||
| 4836 | 97706 | PyTypeObject *parent = child->tp_base; | |
| 4837 | 97706 | return (parent != NULL && | |
| 4838 |
2/2✓ Branch 0 taken 63140 times.
✓ Branch 1 taken 34566 times.
|
97706 | child->tp_basicsize == parent->tp_basicsize && |
| 4839 |
1/2✓ Branch 0 taken 63140 times.
✗ Branch 1 not taken.
|
63140 | child->tp_itemsize == parent->tp_itemsize && |
| 4840 |
1/2✓ Branch 0 taken 63140 times.
✗ Branch 1 not taken.
|
63140 | child->tp_dictoffset == parent->tp_dictoffset && |
| 4841 |
1/2✓ Branch 0 taken 63140 times.
✗ Branch 1 not taken.
|
63140 | child->tp_weaklistoffset == parent->tp_weaklistoffset && |
| 4842 | 63140 | ((child->tp_flags & Py_TPFLAGS_HAVE_GC) == | |
| 4843 |
2/4✓ Branch 0 taken 97706 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 63140 times.
✗ Branch 3 not taken.
|
258552 | (parent->tp_flags & Py_TPFLAGS_HAVE_GC)) && |
| 4844 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 63140 times.
|
63140 | (child->tp_dealloc == subtype_dealloc || |
| 4845 | ✗ | child->tp_dealloc == parent->tp_dealloc)); | |
| 4846 | } | ||
| 4847 | |||
| 4848 | static int | ||
| 4849 | ✗ | same_slots_added(PyTypeObject *a, PyTypeObject *b) | |
| 4850 | { | ||
| 4851 | ✗ | PyTypeObject *base = a->tp_base; | |
| 4852 | Py_ssize_t size; | ||
| 4853 | PyObject *slots_a, *slots_b; | ||
| 4854 | |||
| 4855 | assert(base == b->tp_base); | ||
| 4856 | ✗ | size = base->tp_basicsize; | |
| 4857 | ✗ | if (a->tp_dictoffset == size && b->tp_dictoffset == size) | |
| 4858 | ✗ | size += sizeof(PyObject *); | |
| 4859 | ✗ | if (a->tp_weaklistoffset == size && b->tp_weaklistoffset == size) | |
| 4860 | ✗ | size += sizeof(PyObject *); | |
| 4861 | |||
| 4862 | /* Check slots compliance */ | ||
| 4863 | ✗ | if (!(a->tp_flags & Py_TPFLAGS_HEAPTYPE) || | |
| 4864 | ✗ | !(b->tp_flags & Py_TPFLAGS_HEAPTYPE)) { | |
| 4865 | ✗ | return 0; | |
| 4866 | } | ||
| 4867 | ✗ | slots_a = ((PyHeapTypeObject *)a)->ht_slots; | |
| 4868 | ✗ | slots_b = ((PyHeapTypeObject *)b)->ht_slots; | |
| 4869 | ✗ | if (slots_a && slots_b) { | |
| 4870 | ✗ | if (PyObject_RichCompareBool(slots_a, slots_b, Py_EQ) != 1) | |
| 4871 | ✗ | return 0; | |
| 4872 | ✗ | size += sizeof(PyObject *) * PyTuple_GET_SIZE(slots_a); | |
| 4873 | } | ||
| 4874 | ✗ | return size == a->tp_basicsize && size == b->tp_basicsize; | |
| 4875 | } | ||
| 4876 | |||
| 4877 | static int | ||
| 4878 | 17283 | compatible_for_assignment(PyTypeObject* oldto, PyTypeObject* newto, const char* attr) | |
| 4879 | { | ||
| 4880 | PyTypeObject *newbase, *oldbase; | ||
| 4881 | |||
| 4882 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 17283 times.
|
17283 | if (newto->tp_free != oldto->tp_free) { |
| 4883 | ✗ | PyErr_Format(PyExc_TypeError, | |
| 4884 | "%s assignment: " | ||
| 4885 | "'%s' deallocator differs from '%s'", | ||
| 4886 | attr, | ||
| 4887 | newto->tp_name, | ||
| 4888 | oldto->tp_name); | ||
| 4889 | ✗ | return 0; | |
| 4890 | } | ||
| 4891 | /* | ||
| 4892 | It's tricky to tell if two arbitrary types are sufficiently compatible as | ||
| 4893 | to be interchangeable; e.g., even if they have the same tp_basicsize, they | ||
| 4894 | might have totally different struct fields. It's much easier to tell if a | ||
| 4895 | type and its supertype are compatible; e.g., if they have the same | ||
| 4896 | tp_basicsize, then that means they have identical fields. So to check | ||
| 4897 | whether two arbitrary types are compatible, we first find the highest | ||
| 4898 | supertype that each is compatible with, and then if those supertypes are | ||
| 4899 | compatible then the original types must also be compatible. | ||
| 4900 | */ | ||
| 4901 | 17283 | newbase = newto; | |
| 4902 | 17283 | oldbase = oldto; | |
| 4903 |
2/2✓ Branch 1 taken 37884 times.
✓ Branch 2 taken 17283 times.
|
55167 | while (compatible_with_tp_base(newbase)) |
| 4904 | 37884 | newbase = newbase->tp_base; | |
| 4905 |
2/2✓ Branch 1 taken 25256 times.
✓ Branch 2 taken 17283 times.
|
42539 | while (compatible_with_tp_base(oldbase)) |
| 4906 | 25256 | oldbase = oldbase->tp_base; | |
| 4907 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 17283 times.
|
17283 | if (newbase != oldbase && |
| 4908 | ✗ | (newbase->tp_base != oldbase->tp_base || | |
| 4909 | ✗ | !same_slots_added(newbase, oldbase))) { | |
| 4910 | ✗ | goto differs; | |
| 4911 | } | ||
| 4912 | /* The above does not check for managed __dicts__ */ | ||
| 4913 | 17283 | if ((oldto->tp_flags & Py_TPFLAGS_MANAGED_DICT) == | |
| 4914 |
1/2✓ Branch 0 taken 17283 times.
✗ Branch 1 not taken.
|
17283 | ((newto->tp_flags & Py_TPFLAGS_MANAGED_DICT))) |
| 4915 | { | ||
| 4916 | 17283 | return 1; | |
| 4917 | } | ||
| 4918 | ✗ | differs: | |
| 4919 | ✗ | PyErr_Format(PyExc_TypeError, | |
| 4920 | "%s assignment: " | ||
| 4921 | "'%s' object layout differs from '%s'", | ||
| 4922 | attr, | ||
| 4923 | newto->tp_name, | ||
| 4924 | oldto->tp_name); | ||
| 4925 | ✗ | return 0; | |
| 4926 | } | ||
| 4927 | |||
| 4928 | static int | ||
| 4929 | 12628 | object_set_class(PyObject *self, PyObject *value, void *closure) | |
| 4930 | { | ||
| 4931 | 12628 | PyTypeObject *oldto = Py_TYPE(self); | |
| 4932 | |||
| 4933 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 12628 times.
|
12628 | if (value == NULL) { |
| 4934 | ✗ | PyErr_SetString(PyExc_TypeError, | |
| 4935 | "can't delete __class__ attribute"); | ||
| 4936 | ✗ | return -1; | |
| 4937 | } | ||
| 4938 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 12628 times.
|
12628 | if (!PyType_Check(value)) { |
| 4939 | ✗ | PyErr_Format(PyExc_TypeError, | |
| 4940 | "__class__ must be set to a class, not '%s' object", | ||
| 4941 | ✗ | Py_TYPE(value)->tp_name); | |
| 4942 | ✗ | return -1; | |
| 4943 | } | ||
| 4944 | 12628 | PyTypeObject *newto = (PyTypeObject *)value; | |
| 4945 | |||
| 4946 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 12628 times.
|
12628 | if (PySys_Audit("object.__setattr__", "OsO", |
| 4947 | self, "__class__", value) < 0) { | ||
| 4948 | ✗ | return -1; | |
| 4949 | } | ||
| 4950 | |||
| 4951 | /* In versions of CPython prior to 3.5, the code in | ||
| 4952 | compatible_for_assignment was not set up to correctly check for memory | ||
| 4953 | layout / slot / etc. compatibility for non-HEAPTYPE classes, so we just | ||
| 4954 | disallowed __class__ assignment in any case that wasn't HEAPTYPE -> | ||
| 4955 | HEAPTYPE. | ||
| 4956 | |||
| 4957 | During the 3.5 development cycle, we fixed the code in | ||
| 4958 | compatible_for_assignment to correctly check compatibility between | ||
| 4959 | arbitrary types, and started allowing __class__ assignment in all cases | ||
| 4960 | where the old and new types did in fact have compatible slots and | ||
| 4961 | memory layout (regardless of whether they were implemented as HEAPTYPEs | ||
| 4962 | or not). | ||
| 4963 | |||
| 4964 | Just before 3.5 was released, though, we discovered that this led to | ||
| 4965 | problems with immutable types like int, where the interpreter assumes | ||
| 4966 | they are immutable and interns some values. Formerly this wasn't a | ||
| 4967 | problem, because they really were immutable -- in particular, all the | ||
| 4968 | types where the interpreter applied this interning trick happened to | ||
| 4969 | also be statically allocated, so the old HEAPTYPE rules were | ||
| 4970 | "accidentally" stopping them from allowing __class__ assignment. But | ||
| 4971 | with the changes to __class__ assignment, we started allowing code like | ||
| 4972 | |||
| 4973 | class MyInt(int): | ||
| 4974 | ... | ||
| 4975 | # Modifies the type of *all* instances of 1 in the whole program, | ||
| 4976 | # including future instances (!), because the 1 object is interned. | ||
| 4977 | (1).__class__ = MyInt | ||
| 4978 | |||
| 4979 | (see https://bugs.python.org/issue24912). | ||
| 4980 | |||
| 4981 | In theory the proper fix would be to identify which classes rely on | ||
| 4982 | this invariant and somehow disallow __class__ assignment only for them, | ||
| 4983 | perhaps via some mechanism like a new Py_TPFLAGS_IMMUTABLE flag (a | ||
| 4984 | "denylisting" approach). But in practice, since this problem wasn't | ||
| 4985 | noticed late in the 3.5 RC cycle, we're taking the conservative | ||
| 4986 | approach and reinstating the same HEAPTYPE->HEAPTYPE check that we used | ||
| 4987 | to have, plus an "allowlist". For now, the allowlist consists only of | ||
| 4988 | ModuleType subtypes, since those are the cases that motivated the patch | ||
| 4989 | in the first place -- see https://bugs.python.org/issue22986 -- and | ||
| 4990 | since module objects are mutable we can be sure that they are | ||
| 4991 | definitely not being interned. So now we allow HEAPTYPE->HEAPTYPE *or* | ||
| 4992 | ModuleType subtype -> ModuleType subtype. | ||
| 4993 | |||
| 4994 | So far as we know, all the code beyond the following 'if' statement | ||
| 4995 | will correctly handle non-HEAPTYPE classes, and the HEAPTYPE check is | ||
| 4996 | needed only to protect that subset of non-HEAPTYPE classes for which | ||
| 4997 | the interpreter has baked in the assumption that all instances are | ||
| 4998 | truly immutable. | ||
| 4999 | */ | ||
| 5000 |
1/4✗ Branch 1 not taken.
✓ Branch 2 taken 12628 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
|
12628 | if (!(PyType_IsSubtype(newto, &PyModule_Type) && |
| 5001 |
1/2✓ Branch 1 taken 12628 times.
✗ Branch 2 not taken.
|
12628 | PyType_IsSubtype(oldto, &PyModule_Type)) && |
| 5002 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 12628 times.
|
25256 | (_PyType_HasFeature(newto, Py_TPFLAGS_IMMUTABLETYPE) || |
| 5003 | 12628 | _PyType_HasFeature(oldto, Py_TPFLAGS_IMMUTABLETYPE))) { | |
| 5004 | ✗ | PyErr_Format(PyExc_TypeError, | |
| 5005 | "__class__ assignment only supported for mutable types " | ||
| 5006 | "or ModuleType subclasses"); | ||
| 5007 | ✗ | return -1; | |
| 5008 | } | ||
| 5009 | |||
| 5010 |
1/2✓ Branch 1 taken 12628 times.
✗ Branch 2 not taken.
|
12628 | if (compatible_for_assignment(oldto, newto, "__class__")) { |
| 5011 | /* Changing the class will change the implicit dict keys, | ||
| 5012 | * so we must materialize the dictionary first. */ | ||
| 5013 | assert((oldto->tp_flags & Py_TPFLAGS_MANAGED_DICT) == (newto->tp_flags & Py_TPFLAGS_MANAGED_DICT)); | ||
| 5014 | 12628 | _PyObject_GetDictPtr(self); | |
| 5015 |
2/4✓ Branch 0 taken 12628 times.
✗ Branch 1 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 12628 times.
|
12628 | if (oldto->tp_flags & Py_TPFLAGS_MANAGED_DICT && *_PyObject_ValuesPointer(self)) { |
| 5016 | /* Was unable to convert to dict */ | ||
| 5017 | ✗ | PyErr_NoMemory(); | |
| 5018 | ✗ | return -1; | |
| 5019 | } | ||
| 5020 |
1/2✓ Branch 0 taken 12628 times.
✗ Branch 1 not taken.
|
12628 | if (newto->tp_flags & Py_TPFLAGS_HEAPTYPE) { |
| 5021 | 12628 | Py_INCREF(newto); | |
| 5022 | } | ||
| 5023 | 12628 | Py_SET_TYPE(self, newto); | |
| 5024 |
1/2✓ Branch 0 taken 12628 times.
✗ Branch 1 not taken.
|
12628 | if (oldto->tp_flags & Py_TPFLAGS_HEAPTYPE) |
| 5025 | 12628 | Py_DECREF(oldto); | |
| 5026 | 12628 | return 0; | |
| 5027 | } | ||
| 5028 | else { | ||
| 5029 | ✗ | return -1; | |
| 5030 | } | ||
| 5031 | } | ||
| 5032 | |||
| 5033 | static PyGetSetDef object_getsets[] = { | ||
| 5034 | {"__class__", object_get_class, object_set_class, | ||
| 5035 | PyDoc_STR("the object's class")}, | ||
| 5036 | {0} | ||
| 5037 | }; | ||
| 5038 | |||
| 5039 | |||
| 5040 | /* Stuff to implement __reduce_ex__ for pickle protocols >= 2. | ||
| 5041 | We fall back to helpers in copyreg for: | ||
| 5042 | - pickle protocols < 2 | ||
| 5043 | - calculating the list of slot names (done only once per class) | ||
| 5044 | - the __newobj__ function (which is used as a token but never called) | ||
| 5045 | */ | ||
| 5046 | |||
| 5047 | static PyObject * | ||
| 5048 | 173385 | import_copyreg(void) | |
| 5049 | { | ||
| 5050 | /* Try to fetch cached copy of copyreg from sys.modules first in an | ||
| 5051 | attempt to avoid the import overhead. Previously this was implemented | ||
| 5052 | by storing a reference to the cached module in a static variable, but | ||
| 5053 | this broke when multiple embedded interpreters were in use (see issue | ||
| 5054 | #17408 and #19088). */ | ||
| 5055 | 173385 | PyObject *copyreg_module = PyImport_GetModule(&_Py_ID(copyreg)); | |
| 5056 |
1/2✓ Branch 0 taken 173385 times.
✗ Branch 1 not taken.
|
173385 | if (copyreg_module != NULL) { |
| 5057 | 173385 | return copyreg_module; | |
| 5058 | } | ||
| 5059 | ✗ | if (PyErr_Occurred()) { | |
| 5060 | ✗ | return NULL; | |
| 5061 | } | ||
| 5062 | ✗ | return PyImport_Import(&_Py_ID(copyreg)); | |
| 5063 | } | ||
| 5064 | |||
| 5065 | static PyObject * | ||
| 5066 | 168198 | _PyType_GetSlotNames(PyTypeObject *cls) | |
| 5067 | { | ||
| 5068 | PyObject *copyreg; | ||
| 5069 | PyObject *slotnames; | ||
| 5070 | |||
| 5071 | assert(PyType_Check(cls)); | ||
| 5072 | |||
| 5073 | /* Get the slot names from the cache in the class if possible. */ | ||
| 5074 | 168198 | slotnames = PyDict_GetItemWithError(cls->tp_dict, &_Py_ID(__slotnames__)); | |
| 5075 |
2/2✓ Branch 0 taken 163011 times.
✓ Branch 1 taken 5187 times.
|
168198 | if (slotnames != NULL) { |
| 5076 |
2/4✓ Branch 0 taken 163011 times.
✗ Branch 1 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 163011 times.
|
163011 | if (slotnames != Py_None && !PyList_Check(slotnames)) { |
| 5077 | ✗ | PyErr_Format(PyExc_TypeError, | |
| 5078 | "%.200s.__slotnames__ should be a list or None, " | ||
| 5079 | "not %.200s", | ||
| 5080 | ✗ | cls->tp_name, Py_TYPE(slotnames)->tp_name); | |
| 5081 | ✗ | return NULL; | |
| 5082 | } | ||
| 5083 | 163011 | Py_INCREF(slotnames); | |
| 5084 | 163011 | return slotnames; | |
| 5085 | } | ||
| 5086 | else { | ||
| 5087 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 5187 times.
|
5187 | if (PyErr_Occurred()) { |
| 5088 | ✗ | return NULL; | |
| 5089 | } | ||
| 5090 | /* The class does not have the slot names cached yet. */ | ||
| 5091 | } | ||
| 5092 | |||
| 5093 | 5187 | copyreg = import_copyreg(); | |
| 5094 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5187 times.
|
5187 | if (copyreg == NULL) |
| 5095 | ✗ | return NULL; | |
| 5096 | |||
| 5097 | /* Use _slotnames function from the copyreg module to find the slots | ||
| 5098 | by this class and its bases. This function will cache the result | ||
| 5099 | in __slotnames__. */ | ||
| 5100 | 5187 | slotnames = PyObject_CallMethodOneArg( | |
| 5101 | copyreg, &_Py_ID(_slotnames), (PyObject *)cls); | ||
| 5102 | 5187 | Py_DECREF(copyreg); | |
| 5103 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5187 times.
|
5187 | if (slotnames == NULL) |
| 5104 | ✗ | return NULL; | |
| 5105 | |||
| 5106 |
2/4✓ Branch 0 taken 5187 times.
✗ Branch 1 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 5187 times.
|
5187 | if (slotnames != Py_None && !PyList_Check(slotnames)) { |
| 5107 | ✗ | PyErr_SetString(PyExc_TypeError, | |
| 5108 | "copyreg._slotnames didn't return a list or None"); | ||
| 5109 | ✗ | Py_DECREF(slotnames); | |
| 5110 | ✗ | return NULL; | |
| 5111 | } | ||
| 5112 | |||
| 5113 | 5187 | return slotnames; | |
| 5114 | } | ||
| 5115 | |||
| 5116 | static PyObject * | ||
| 5117 | 168198 | object_getstate_default(PyObject *obj, int required) | |
| 5118 | { | ||
| 5119 | PyObject *state; | ||
| 5120 | PyObject *slotnames; | ||
| 5121 | |||
| 5122 |
2/4✓ Branch 0 taken 168198 times.
✗ Branch 1 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 168198 times.
|
168198 | if (required && Py_TYPE(obj)->tp_itemsize) { |
| 5123 | ✗ | PyErr_Format(PyExc_TypeError, | |
| 5124 | "cannot pickle %.200s objects", | ||
| 5125 | ✗ | Py_TYPE(obj)->tp_name); | |
| 5126 | ✗ | return NULL; | |
| 5127 | } | ||
| 5128 | |||
| 5129 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 168198 times.
|
168198 | if (_PyObject_IsInstanceDictEmpty(obj)) { |
| 5130 | ✗ | state = Py_None; | |
| 5131 | ✗ | Py_INCREF(state); | |
| 5132 | } | ||
| 5133 | else { | ||
| 5134 | 168198 | state = PyObject_GenericGetDict(obj, NULL); | |
| 5135 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 168198 times.
|
168198 | if (state == NULL) { |
| 5136 | ✗ | return NULL; | |
| 5137 | } | ||
| 5138 | } | ||
| 5139 | |||
| 5140 | 168198 | slotnames = _PyType_GetSlotNames(Py_TYPE(obj)); | |
| 5141 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 168198 times.
|
168198 | if (slotnames == NULL) { |
| 5142 | ✗ | Py_DECREF(state); | |
| 5143 | ✗ | return NULL; | |
| 5144 | } | ||
| 5145 | |||
| 5146 | assert(slotnames == Py_None || PyList_Check(slotnames)); | ||
| 5147 |
1/2✓ Branch 0 taken 168198 times.
✗ Branch 1 not taken.
|
168198 | if (required) { |
| 5148 | 168198 | Py_ssize_t basicsize = PyBaseObject_Type.tp_basicsize; | |
| 5149 |
1/2✓ Branch 1 taken 168198 times.
✗ Branch 2 not taken.
|
168198 | if (Py_TYPE(obj)->tp_dictoffset && |
| 5150 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 168198 times.
|
168198 | (Py_TYPE(obj)->tp_flags & Py_TPFLAGS_MANAGED_DICT) == 0) |
| 5151 | { | ||
| 5152 | ✗ | basicsize += sizeof(PyObject *); | |
| 5153 | } | ||
| 5154 |
1/2✓ Branch 1 taken 168198 times.
✗ Branch 2 not taken.
|
168198 | if (Py_TYPE(obj)->tp_weaklistoffset) { |
| 5155 | 168198 | basicsize += sizeof(PyObject *); | |
| 5156 | } | ||
| 5157 |
1/2✓ Branch 0 taken 168198 times.
✗ Branch 1 not taken.
|
168198 | if (slotnames != Py_None) { |
| 5158 | 168198 | basicsize += sizeof(PyObject *) * PyList_GET_SIZE(slotnames); | |
| 5159 | } | ||
| 5160 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 168198 times.
|
168198 | if (Py_TYPE(obj)->tp_basicsize > basicsize) { |
| 5161 | ✗ | Py_DECREF(slotnames); | |
| 5162 | ✗ | Py_DECREF(state); | |
| 5163 | ✗ | PyErr_Format(PyExc_TypeError, | |
| 5164 | "cannot pickle '%.200s' object", | ||
| 5165 | ✗ | Py_TYPE(obj)->tp_name); | |
| 5166 | ✗ | return NULL; | |
| 5167 | } | ||
| 5168 | } | ||
| 5169 | |||
| 5170 |
2/4✓ Branch 0 taken 168198 times.
✗ Branch 1 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 168198 times.
|
168198 | if (slotnames != Py_None && PyList_GET_SIZE(slotnames) > 0) { |
| 5171 | PyObject *slots; | ||
| 5172 | Py_ssize_t slotnames_size, i; | ||
| 5173 | |||
| 5174 | ✗ | slots = PyDict_New(); | |
| 5175 | ✗ | if (slots == NULL) { | |
| 5176 | ✗ | Py_DECREF(slotnames); | |
| 5177 | ✗ | Py_DECREF(state); | |
| 5178 | ✗ | return NULL; | |
| 5179 | } | ||
| 5180 | |||
| 5181 | ✗ | slotnames_size = PyList_GET_SIZE(slotnames); | |
| 5182 | ✗ | for (i = 0; i < slotnames_size; i++) { | |
| 5183 | PyObject *name, *value; | ||
| 5184 | |||
| 5185 | ✗ | name = PyList_GET_ITEM(slotnames, i); | |
| 5186 | ✗ | Py_INCREF(name); | |
| 5187 | ✗ | if (_PyObject_LookupAttr(obj, name, &value) < 0) { | |
| 5188 | ✗ | Py_DECREF(name); | |
| 5189 | ✗ | goto error; | |
| 5190 | } | ||
| 5191 | ✗ | if (value == NULL) { | |
| 5192 | ✗ | Py_DECREF(name); | |
| 5193 | /* It is not an error if the attribute is not present. */ | ||
| 5194 | } | ||
| 5195 | else { | ||
| 5196 | ✗ | int err = PyDict_SetItem(slots, name, value); | |
| 5197 | ✗ | Py_DECREF(name); | |
| 5198 | ✗ | Py_DECREF(value); | |
| 5199 | ✗ | if (err) { | |
| 5200 | ✗ | goto error; | |
| 5201 | } | ||
| 5202 | } | ||
| 5203 | |||
| 5204 | /* The list is stored on the class so it may mutate while we | ||
| 5205 | iterate over it */ | ||
| 5206 | ✗ | if (slotnames_size != PyList_GET_SIZE(slotnames)) { | |
| 5207 | ✗ | PyErr_Format(PyExc_RuntimeError, | |
| 5208 | "__slotsname__ changed size during iteration"); | ||
| 5209 | ✗ | goto error; | |
| 5210 | } | ||
| 5211 | |||
| 5212 | /* We handle errors within the loop here. */ | ||
| 5213 | if (0) { | ||
| 5214 | ✗ | error: | |
| 5215 | ✗ | Py_DECREF(slotnames); | |
| 5216 | ✗ | Py_DECREF(slots); | |
| 5217 | ✗ | Py_DECREF(state); | |
| 5218 | ✗ | return NULL; | |
| 5219 | } | ||
| 5220 | } | ||
| 5221 | |||
| 5222 | /* If we found some slot attributes, pack them in a tuple along | ||
| 5223 | the original attribute dictionary. */ | ||
| 5224 | ✗ | if (PyDict_GET_SIZE(slots) > 0) { | |
| 5225 | PyObject *state2; | ||
| 5226 | |||
| 5227 | ✗ | state2 = PyTuple_Pack(2, state, slots); | |
| 5228 | ✗ | Py_DECREF(state); | |
| 5229 | ✗ | if (state2 == NULL) { | |
| 5230 | ✗ | Py_DECREF(slotnames); | |
| 5231 | ✗ | Py_DECREF(slots); | |
| 5232 | ✗ | return NULL; | |
| 5233 | } | ||
| 5234 | ✗ | state = state2; | |
| 5235 | } | ||
| 5236 | ✗ | Py_DECREF(slots); | |
| 5237 | } | ||
| 5238 | 168198 | Py_DECREF(slotnames); | |
| 5239 | |||
| 5240 | 168198 | return state; | |
| 5241 | } | ||
| 5242 | |||
| 5243 | static PyObject * | ||
| 5244 | 168198 | object_getstate(PyObject *obj, int required) | |
| 5245 | { | ||
| 5246 | PyObject *getstate, *state; | ||
| 5247 | |||
| 5248 | 168198 | getstate = PyObject_GetAttr(obj, &_Py_ID(__getstate__)); | |
| 5249 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 168198 times.
|
168198 | if (getstate == NULL) { |
| 5250 | ✗ | return NULL; | |
| 5251 | } | ||
| 5252 |
2/4✓ Branch 1 taken 168198 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 168198 times.
✗ Branch 4 not taken.
|
336396 | if (PyCFunction_Check(getstate) && |
| 5253 |
1/2✓ Branch 1 taken 168198 times.
✗ Branch 2 not taken.
|
336396 | PyCFunction_GET_SELF(getstate) == obj && |
| 5254 | 168198 | PyCFunction_GET_FUNCTION(getstate) == object___getstate__) | |
| 5255 | { | ||
| 5256 | /* If __getstate__ is not overriden pass the required argument. */ | ||
| 5257 | 168198 | state = object_getstate_default(obj, required); | |
| 5258 | } | ||
| 5259 | else { | ||
| 5260 | ✗ | state = _PyObject_CallNoArgs(getstate); | |
| 5261 | } | ||
| 5262 | 168198 | Py_DECREF(getstate); | |
| 5263 | 168198 | return state; | |
| 5264 | } | ||
| 5265 | |||
| 5266 | PyObject * | ||
| 5267 | ✗ | _PyObject_GetState(PyObject *obj) | |
| 5268 | { | ||
| 5269 | ✗ | return object_getstate(obj, 0); | |
| 5270 | } | ||
| 5271 | |||
| 5272 | /*[clinic input] | ||
| 5273 | object.__getstate__ | ||
| 5274 | |||
| 5275 | Helper for pickle. | ||
| 5276 | [clinic start generated code]*/ | ||
| 5277 | |||
| 5278 | static PyObject * | ||
| 5279 | ✗ | object___getstate___impl(PyObject *self) | |
| 5280 | /*[clinic end generated code: output=5a2500dcb6217e9e input=692314d8fbe194ee]*/ | ||
| 5281 | { | ||
| 5282 | ✗ | return object_getstate_default(self, 0); | |
| 5283 | } | ||
| 5284 | |||
| 5285 | static int | ||
| 5286 | 168198 | _PyObject_GetNewArguments(PyObject *obj, PyObject **args, PyObject **kwargs) | |
| 5287 | { | ||
| 5288 | PyObject *getnewargs, *getnewargs_ex; | ||
| 5289 | |||
| 5290 |
2/4✓ Branch 0 taken 168198 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 168198 times.
|
168198 | if (args == NULL || kwargs == NULL) { |
| 5291 | ✗ | PyErr_BadInternalCall(); | |
| 5292 | ✗ | return -1; | |
| 5293 | } | ||
| 5294 | |||
| 5295 | /* We first attempt to fetch the arguments for __new__ by calling | ||
| 5296 | __getnewargs_ex__ on the object. */ | ||
| 5297 | 168198 | getnewargs_ex = _PyObject_LookupSpecial(obj, &_Py_ID(__getnewargs_ex__)); | |
| 5298 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 168198 times.
|
168198 | if (getnewargs_ex != NULL) { |
| 5299 | ✗ | PyObject *newargs = _PyObject_CallNoArgs(getnewargs_ex); | |
| 5300 | ✗ | Py_DECREF(getnewargs_ex); | |
| 5301 | ✗ | if (newargs == NULL) { | |
| 5302 | ✗ | return -1; | |
| 5303 | } | ||
| 5304 | ✗ | if (!PyTuple_Check(newargs)) { | |
| 5305 | ✗ | PyErr_Format(PyExc_TypeError, | |
| 5306 | "__getnewargs_ex__ should return a tuple, " | ||
| 5307 | ✗ | "not '%.200s'", Py_TYPE(newargs)->tp_name); | |
| 5308 | ✗ | Py_DECREF(newargs); | |
| 5309 | ✗ | return -1; | |
| 5310 | } | ||
| 5311 | ✗ | if (PyTuple_GET_SIZE(newargs) != 2) { | |
| 5312 | ✗ | PyErr_Format(PyExc_ValueError, | |
| 5313 | "__getnewargs_ex__ should return a tuple of " | ||
| 5314 | "length 2, not %zd", PyTuple_GET_SIZE(newargs)); | ||
| 5315 | ✗ | Py_DECREF(newargs); | |
| 5316 | ✗ | return -1; | |
| 5317 | } | ||
| 5318 | ✗ | *args = PyTuple_GET_ITEM(newargs, 0); | |
| 5319 | ✗ | Py_INCREF(*args); | |
| 5320 | ✗ | *kwargs = PyTuple_GET_ITEM(newargs, 1); | |
| 5321 | ✗ | Py_INCREF(*kwargs); | |
| 5322 | ✗ | Py_DECREF(newargs); | |
| 5323 | |||
| 5324 | /* XXX We should perhaps allow None to be passed here. */ | ||
| 5325 | ✗ | if (!PyTuple_Check(*args)) { | |
| 5326 | ✗ | PyErr_Format(PyExc_TypeError, | |
| 5327 | "first item of the tuple returned by " | ||
| 5328 | "__getnewargs_ex__ must be a tuple, not '%.200s'", | ||
| 5329 | ✗ | Py_TYPE(*args)->tp_name); | |
| 5330 | ✗ | Py_CLEAR(*args); | |
| 5331 | ✗ | Py_CLEAR(*kwargs); | |
| 5332 | ✗ | return -1; | |
| 5333 | } | ||
| 5334 | ✗ | if (!PyDict_Check(*kwargs)) { | |
| 5335 | ✗ | PyErr_Format(PyExc_TypeError, | |
| 5336 | "second item of the tuple returned by " | ||
| 5337 | "__getnewargs_ex__ must be a dict, not '%.200s'", | ||
| 5338 | ✗ | Py_TYPE(*kwargs)->tp_name); | |
| 5339 | ✗ | Py_CLEAR(*args); | |
| 5340 | ✗ | Py_CLEAR(*kwargs); | |
| 5341 | ✗ | return -1; | |
| 5342 | } | ||
| 5343 | ✗ | return 0; | |
| 5344 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 168198 times.
|
168198 | } else if (PyErr_Occurred()) { |
| 5345 | ✗ | return -1; | |
| 5346 | } | ||
| 5347 | |||
| 5348 | /* The object does not have __getnewargs_ex__ so we fallback on using | ||
| 5349 | __getnewargs__ instead. */ | ||
| 5350 | 168198 | getnewargs = _PyObject_LookupSpecial(obj, &_Py_ID(__getnewargs__)); | |
| 5351 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 168198 times.
|
168198 | if (getnewargs != NULL) { |
| 5352 | ✗ | *args = _PyObject_CallNoArgs(getnewargs); | |
| 5353 | ✗ | Py_DECREF(getnewargs); | |
| 5354 | ✗ | if (*args == NULL) { | |
| 5355 | ✗ | return -1; | |
| 5356 | } | ||
| 5357 | ✗ | if (!PyTuple_Check(*args)) { | |
| 5358 | ✗ | PyErr_Format(PyExc_TypeError, | |
| 5359 | "__getnewargs__ should return a tuple, " | ||
| 5360 | ✗ | "not '%.200s'", Py_TYPE(*args)->tp_name); | |
| 5361 | ✗ | Py_CLEAR(*args); | |
| 5362 | ✗ | return -1; | |
| 5363 | } | ||
| 5364 | ✗ | *kwargs = NULL; | |
| 5365 | ✗ | return 0; | |
| 5366 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 168198 times.
|
168198 | } else if (PyErr_Occurred()) { |
| 5367 | ✗ | return -1; | |
| 5368 | } | ||
| 5369 | |||
| 5370 | /* The object does not have __getnewargs_ex__ and __getnewargs__. This may | ||
| 5371 | mean __new__ does not takes any arguments on this object, or that the | ||
| 5372 | object does not implement the reduce protocol for pickling or | ||
| 5373 | copying. */ | ||
| 5374 | 168198 | *args = NULL; | |
| 5375 | 168198 | *kwargs = NULL; | |
| 5376 | 168198 | return 0; | |
| 5377 | } | ||
| 5378 | |||
| 5379 | static int | ||
| 5380 | 168198 | _PyObject_GetItemsIter(PyObject *obj, PyObject **listitems, | |
| 5381 | PyObject **dictitems) | ||
| 5382 | { | ||
| 5383 |
2/4✓ Branch 0 taken 168198 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 168198 times.
|
168198 | if (listitems == NULL || dictitems == NULL) { |
| 5384 | ✗ | PyErr_BadInternalCall(); | |
| 5385 | ✗ | return -1; | |
| 5386 | } | ||
| 5387 | |||
| 5388 |
1/2✓ Branch 2 taken 168198 times.
✗ Branch 3 not taken.
|
168198 | if (!PyList_Check(obj)) { |
| 5389 | 168198 | *listitems = Py_None; | |
| 5390 | 168198 | Py_INCREF(*listitems); | |
| 5391 | } | ||
| 5392 | else { | ||
| 5393 | ✗ | *listitems = PyObject_GetIter(obj); | |
| 5394 | ✗ | if (*listitems == NULL) | |
| 5395 | ✗ | return -1; | |
| 5396 | } | ||
| 5397 | |||
| 5398 |
1/2✓ Branch 2 taken 168198 times.
✗ Branch 3 not taken.
|
168198 | if (!PyDict_Check(obj)) { |
| 5399 | 168198 | *dictitems = Py_None; | |
| 5400 | 168198 | Py_INCREF(*dictitems); | |
| 5401 | } | ||
| 5402 | else { | ||
| 5403 | ✗ | PyObject *items = PyObject_CallMethodNoArgs(obj, &_Py_ID(items)); | |
| 5404 | ✗ | if (items == NULL) { | |
| 5405 | ✗ | Py_CLEAR(*listitems); | |
| 5406 | ✗ | return -1; | |
| 5407 | } | ||
| 5408 | ✗ | *dictitems = PyObject_GetIter(items); | |
| 5409 | ✗ | Py_DECREF(items); | |
| 5410 | ✗ | if (*dictitems == NULL) { | |
| 5411 | ✗ | Py_CLEAR(*listitems); | |
| 5412 | ✗ | return -1; | |
| 5413 | } | ||
| 5414 | } | ||
| 5415 | |||
| 5416 | assert(*listitems != NULL && *dictitems != NULL); | ||
| 5417 | |||
| 5418 | 168198 | return 0; | |
| 5419 | } | ||
| 5420 | |||
| 5421 | static PyObject * | ||
| 5422 | 168198 | reduce_newobj(PyObject *obj) | |
| 5423 | { | ||
| 5424 | 168198 | PyObject *args = NULL, *kwargs = NULL; | |
| 5425 | PyObject *copyreg; | ||
| 5426 | PyObject *newobj, *newargs, *state, *listitems, *dictitems; | ||
| 5427 | PyObject *result; | ||
| 5428 | int hasargs; | ||
| 5429 | |||
| 5430 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 168198 times.
|
168198 | if (Py_TYPE(obj)->tp_new == NULL) { |
| 5431 | ✗ | PyErr_Format(PyExc_TypeError, | |
| 5432 | "cannot pickle '%.200s' object", | ||
| 5433 | ✗ | Py_TYPE(obj)->tp_name); | |
| 5434 | ✗ | return NULL; | |
| 5435 | } | ||
| 5436 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 168198 times.
|
168198 | if (_PyObject_GetNewArguments(obj, &args, &kwargs) < 0) |
| 5437 | ✗ | return NULL; | |
| 5438 | |||
| 5439 | 168198 | copyreg = import_copyreg(); | |
| 5440 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 168198 times.
|
168198 | if (copyreg == NULL) { |
| 5441 | ✗ | Py_XDECREF(args); | |
| 5442 | ✗ | Py_XDECREF(kwargs); | |
| 5443 | ✗ | return NULL; | |
| 5444 | } | ||
| 5445 | 168198 | hasargs = (args != NULL); | |
| 5446 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 168198 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
|
336396 | if (kwargs == NULL || PyDict_GET_SIZE(kwargs) == 0) { |
| 5447 | PyObject *cls; | ||
| 5448 | Py_ssize_t i, n; | ||
| 5449 | |||
| 5450 | 168198 | Py_XDECREF(kwargs); | |
| 5451 | 168198 | newobj = PyObject_GetAttr(copyreg, &_Py_ID(__newobj__)); | |
| 5452 | 168198 | Py_DECREF(copyreg); | |
| 5453 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 168198 times.
|
168198 | if (newobj == NULL) { |
| 5454 | ✗ | Py_XDECREF(args); | |
| 5455 | ✗ | return NULL; | |
| 5456 | } | ||
| 5457 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 168198 times.
|
168198 | n = args ? PyTuple_GET_SIZE(args) : 0; |
| 5458 | 168198 | newargs = PyTuple_New(n+1); | |
| 5459 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 168198 times.
|
168198 | if (newargs == NULL) { |
| 5460 | ✗ | Py_XDECREF(args); | |
| 5461 | ✗ | Py_DECREF(newobj); | |
| 5462 | ✗ | return NULL; | |
| 5463 | } | ||
| 5464 | 168198 | cls = (PyObject *) Py_TYPE(obj); | |
| 5465 | 168198 | Py_INCREF(cls); | |
| 5466 | 168198 | PyTuple_SET_ITEM(newargs, 0, cls); | |
| 5467 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 168198 times.
|
168198 | for (i = 0; i < n; i++) { |
| 5468 | ✗ | PyObject *v = PyTuple_GET_ITEM(args, i); | |
| 5469 | ✗ | Py_INCREF(v); | |
| 5470 | ✗ | PyTuple_SET_ITEM(newargs, i+1, v); | |
| 5471 | } | ||
| 5472 | 168198 | Py_XDECREF(args); | |
| 5473 | } | ||
| 5474 | ✗ | else if (args != NULL) { | |
| 5475 | ✗ | newobj = PyObject_GetAttr(copyreg, &_Py_ID(__newobj_ex__)); | |
| 5476 | ✗ | Py_DECREF(copyreg); | |
| 5477 | ✗ | if (newobj == NULL) { | |
| 5478 | ✗ | Py_DECREF(args); | |
| 5479 | ✗ | Py_DECREF(kwargs); | |
| 5480 | ✗ | return NULL; | |
| 5481 | } | ||
| 5482 | ✗ | newargs = PyTuple_Pack(3, Py_TYPE(obj), args, kwargs); | |
| 5483 | ✗ | Py_DECREF(args); | |
| 5484 | ✗ | Py_DECREF(kwargs); | |
| 5485 | ✗ | if (newargs == NULL) { | |
| 5486 | ✗ | Py_DECREF(newobj); | |
| 5487 | ✗ | return NULL; | |
| 5488 | } | ||
| 5489 | } | ||
| 5490 | else { | ||
| 5491 | /* args == NULL */ | ||
| 5492 | ✗ | Py_DECREF(kwargs); | |
| 5493 | ✗ | PyErr_BadInternalCall(); | |
| 5494 | ✗ | return NULL; | |
| 5495 | } | ||
| 5496 | |||
| 5497 |
3/6✓ Branch 0 taken 168198 times.
✗ Branch 1 not taken.
✓ Branch 4 taken 168198 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 168198 times.
✗ Branch 9 not taken.
|
168198 | state = object_getstate(obj, !(hasargs || PyList_Check(obj) || PyDict_Check(obj))); |
| 5498 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 168198 times.
|
168198 | if (state == NULL) { |
| 5499 | ✗ | Py_DECREF(newobj); | |
| 5500 | ✗ | Py_DECREF(newargs); | |
| 5501 | ✗ | return NULL; | |
| 5502 | } | ||
| 5503 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 168198 times.
|
168198 | if (_PyObject_GetItemsIter(obj, &listitems, &dictitems) < 0) { |
| 5504 | ✗ | Py_DECREF(newobj); | |
| 5505 | ✗ | Py_DECREF(newargs); | |
| 5506 | ✗ | Py_DECREF(state); | |
| 5507 | ✗ | return NULL; | |
| 5508 | } | ||
| 5509 | |||
| 5510 | 168198 | result = PyTuple_Pack(5, newobj, newargs, state, listitems, dictitems); | |
| 5511 | 168198 | Py_DECREF(newobj); | |
| 5512 | 168198 | Py_DECREF(newargs); | |
| 5513 | 168198 | Py_DECREF(state); | |
| 5514 | 168198 | Py_DECREF(listitems); | |
| 5515 | 168198 | Py_DECREF(dictitems); | |
| 5516 | 168198 | return result; | |
| 5517 | } | ||
| 5518 | |||
| 5519 | /* | ||
| 5520 | * There were two problems when object.__reduce__ and object.__reduce_ex__ | ||
| 5521 | * were implemented in the same function: | ||
| 5522 | * - trying to pickle an object with a custom __reduce__ method that | ||
| 5523 | * fell back to object.__reduce__ in certain circumstances led to | ||
| 5524 | * infinite recursion at Python level and eventual RecursionError. | ||
| 5525 | * - Pickling objects that lied about their type by overwriting the | ||
| 5526 | * __class__ descriptor could lead to infinite recursion at C level | ||
| 5527 | * and eventual segfault. | ||
| 5528 | * | ||
| 5529 | * Because of backwards compatibility, the two methods still have to | ||
| 5530 | * behave in the same way, even if this is not required by the pickle | ||
| 5531 | * protocol. This common functionality was moved to the _common_reduce | ||
| 5532 | * function. | ||
| 5533 | */ | ||
| 5534 | static PyObject * | ||
| 5535 | 168198 | _common_reduce(PyObject *self, int proto) | |
| 5536 | { | ||
| 5537 | PyObject *copyreg, *res; | ||
| 5538 | |||
| 5539 |
1/2✓ Branch 0 taken 168198 times.
✗ Branch 1 not taken.
|
168198 | if (proto >= 2) |
| 5540 | 168198 | return reduce_newobj(self); | |
| 5541 | |||
| 5542 | ✗ | copyreg = import_copyreg(); | |
| 5543 | ✗ | if (!copyreg) | |
| 5544 | ✗ | return NULL; | |
| 5545 | |||
| 5546 | ✗ | res = PyObject_CallMethod(copyreg, "_reduce_ex", "Oi", self, proto); | |
| 5547 | ✗ | Py_DECREF(copyreg); | |
| 5548 | |||
| 5549 | ✗ | return res; | |
| 5550 | } | ||
| 5551 | |||
| 5552 | /*[clinic input] | ||
| 5553 | object.__reduce__ | ||
| 5554 | |||
| 5555 | Helper for pickle. | ||
| 5556 | [clinic start generated code]*/ | ||
| 5557 | |||
| 5558 | static PyObject * | ||
| 5559 | ✗ | object___reduce___impl(PyObject *self) | |
| 5560 | /*[clinic end generated code: output=d4ca691f891c6e2f input=11562e663947e18b]*/ | ||
| 5561 | { | ||
| 5562 | ✗ | return _common_reduce(self, 0); | |
| 5563 | } | ||
| 5564 | |||
| 5565 | /*[clinic input] | ||
| 5566 | object.__reduce_ex__ | ||
| 5567 | |||
| 5568 | protocol: int | ||
| 5569 | / | ||
| 5570 | |||
| 5571 | Helper for pickle. | ||
| 5572 | [clinic start generated code]*/ | ||
| 5573 | |||
| 5574 | static PyObject * | ||
| 5575 | 398510 | object___reduce_ex___impl(PyObject *self, int protocol) | |
| 5576 | /*[clinic end generated code: output=2e157766f6b50094 input=f326b43fb8a4c5ff]*/ | ||
| 5577 | { | ||
| 5578 | static PyObject *objreduce; | ||
| 5579 | PyObject *reduce, *res; | ||
| 5580 | |||
| 5581 |
2/2✓ Branch 0 taken 397 times.
✓ Branch 1 taken 398113 times.
|
398510 | if (objreduce == NULL) { |
| 5582 | 397 | objreduce = PyDict_GetItemWithError( | |
| 5583 | PyBaseObject_Type.tp_dict, &_Py_ID(__reduce__)); | ||
| 5584 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 397 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
|
397 | if (objreduce == NULL && PyErr_Occurred()) { |
| 5585 | ✗ | return NULL; | |
| 5586 | } | ||
| 5587 | } | ||
| 5588 | |||
| 5589 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 398510 times.
|
398510 | if (_PyObject_LookupAttr(self, &_Py_ID(__reduce__), &reduce) < 0) { |
| 5590 | ✗ | return NULL; | |
| 5591 | } | ||
| 5592 |
1/2✓ Branch 0 taken 398510 times.
✗ Branch 1 not taken.
|
398510 | if (reduce != NULL) { |
| 5593 | PyObject *cls, *clsreduce; | ||
| 5594 | int override; | ||
| 5595 | |||
| 5596 | 398510 | cls = (PyObject *) Py_TYPE(self); | |
| 5597 | 398510 | clsreduce = PyObject_GetAttr(cls, &_Py_ID(__reduce__)); | |
| 5598 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 398510 times.
|
398510 | if (clsreduce == NULL) { |
| 5599 | ✗ | Py_DECREF(reduce); | |
| 5600 | ✗ | return NULL; | |
| 5601 | } | ||
| 5602 | 398510 | override = (clsreduce != objreduce); | |
| 5603 | 398510 | Py_DECREF(clsreduce); | |
| 5604 |
2/2✓ Branch 0 taken 230312 times.
✓ Branch 1 taken 168198 times.
|
398510 | if (override) { |
| 5605 | 230312 | res = _PyObject_CallNoArgs(reduce); | |
| 5606 | 230312 | Py_DECREF(reduce); | |
| 5607 | 230312 | return res; | |
| 5608 | } | ||
| 5609 | else | ||
| 5610 | 168198 | Py_DECREF(reduce); | |
| 5611 | } | ||
| 5612 | |||
| 5613 | 168198 | return _common_reduce(self, protocol); | |
| 5614 | } | ||
| 5615 | |||
| 5616 | static PyObject * | ||
| 5617 | 693628 | object_subclasshook(PyObject *cls, PyObject *args) | |
| 5618 | { | ||
| 5619 | 693628 | Py_RETURN_NOTIMPLEMENTED; | |
| 5620 | } | ||
| 5621 | |||
| 5622 | PyDoc_STRVAR(object_subclasshook_doc, | ||
| 5623 | "Abstract classes can override this to customize issubclass().\n" | ||
| 5624 | "\n" | ||
| 5625 | "This is invoked early on by abc.ABCMeta.__subclasscheck__().\n" | ||
| 5626 | "It should return True, False or NotImplemented. If it returns\n" | ||
| 5627 | "NotImplemented, the normal algorithm is used. Otherwise, it\n" | ||
| 5628 | "overrides the normal algorithm (and the outcome is cached).\n"); | ||
| 5629 | |||
| 5630 | static PyObject * | ||
| 5631 | 1569085 | object_init_subclass(PyObject *cls, PyObject *arg) | |
| 5632 | { | ||
| 5633 | 1569085 | Py_RETURN_NONE; | |
| 5634 | } | ||
| 5635 | |||
| 5636 | PyDoc_STRVAR(object_init_subclass_doc, | ||
| 5637 | "This method is called when a class is subclassed.\n" | ||
| 5638 | "\n" | ||
| 5639 | "The default implementation does nothing. It may be\n" | ||
| 5640 | "overridden to extend subclasses.\n"); | ||
| 5641 | |||
| 5642 | /*[clinic input] | ||
| 5643 | object.__format__ | ||
| 5644 | |||
| 5645 | format_spec: unicode | ||
| 5646 | / | ||
| 5647 | |||
| 5648 | Default object formatter. | ||
| 5649 | [clinic start generated code]*/ | ||
| 5650 | |||
| 5651 | static PyObject * | ||
| 5652 | 58378 | object___format___impl(PyObject *self, PyObject *format_spec) | |
| 5653 | /*[clinic end generated code: output=34897efb543a974b input=7c3b3bc53a6fb7fa]*/ | ||
| 5654 | { | ||
| 5655 | /* Issue 7994: If we're converting to a string, we | ||
| 5656 | should reject format specifications */ | ||
| 5657 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 58378 times.
|
58378 | if (PyUnicode_GET_LENGTH(format_spec) > 0) { |
| 5658 | ✗ | PyErr_Format(PyExc_TypeError, | |
| 5659 | "unsupported format string passed to %.200s.__format__", | ||
| 5660 | ✗ | Py_TYPE(self)->tp_name); | |
| 5661 | ✗ | return NULL; | |
| 5662 | } | ||
| 5663 | 58378 | return PyObject_Str(self); | |
| 5664 | } | ||
| 5665 | |||
| 5666 | /*[clinic input] | ||
| 5667 | object.__sizeof__ | ||
| 5668 | |||
| 5669 | Size of object in memory, in bytes. | ||
| 5670 | [clinic start generated code]*/ | ||
| 5671 | |||
| 5672 | static PyObject * | ||
| 5673 | ✗ | object___sizeof___impl(PyObject *self) | |
| 5674 | /*[clinic end generated code: output=73edab332f97d550 input=1200ff3dfe485306]*/ | ||
| 5675 | { | ||
| 5676 | Py_ssize_t res, isize; | ||
| 5677 | |||
| 5678 | ✗ | res = 0; | |
| 5679 | ✗ | isize = Py_TYPE(self)->tp_itemsize; | |
| 5680 | ✗ | if (isize > 0) | |
| 5681 | ✗ | res = Py_SIZE(self) * isize; | |
| 5682 | ✗ | res += Py_TYPE(self)->tp_basicsize; | |
| 5683 | |||
| 5684 | ✗ | return PyLong_FromSsize_t(res); | |
| 5685 | } | ||
| 5686 | |||
| 5687 | /* __dir__ for generic objects: returns __dict__, __class__, | ||
| 5688 | and recursively up the __class__.__bases__ chain. | ||
| 5689 | */ | ||
| 5690 | /*[clinic input] | ||
| 5691 | object.__dir__ | ||
| 5692 | |||
| 5693 | Default dir() implementation. | ||
| 5694 | [clinic start generated code]*/ | ||
| 5695 | |||
| 5696 | static PyObject * | ||
| 5697 | 3627 | object___dir___impl(PyObject *self) | |
| 5698 | /*[clinic end generated code: output=66dd48ea62f26c90 input=0a89305bec669b10]*/ | ||
| 5699 | { | ||
| 5700 | 3627 | PyObject *result = NULL; | |
| 5701 | 3627 | PyObject *dict = NULL; | |
| 5702 | 3627 | PyObject *itsclass = NULL; | |
| 5703 | |||
| 5704 | /* Get __dict__ (which may or may not be a real dict...) */ | ||
| 5705 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 3627 times.
|
3627 | if (_PyObject_LookupAttr(self, &_Py_ID(__dict__), &dict) < 0) { |
| 5706 | ✗ | return NULL; | |
| 5707 | } | ||
| 5708 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3627 times.
|
3627 | if (dict == NULL) { |
| 5709 | ✗ | dict = PyDict_New(); | |
| 5710 | } | ||
| 5711 |
1/2✗ Branch 2 not taken.
✓ Branch 3 taken 3627 times.
|
3627 | else if (!PyDict_Check(dict)) { |
| 5712 | ✗ | Py_DECREF(dict); | |
| 5713 | ✗ | dict = PyDict_New(); | |
| 5714 | } | ||
| 5715 | else { | ||
| 5716 | /* Copy __dict__ to avoid mutating it. */ | ||
| 5717 | 3627 | PyObject *temp = PyDict_Copy(dict); | |
| 5718 | 3627 | Py_DECREF(dict); | |
| 5719 | 3627 | dict = temp; | |
| 5720 | } | ||
| 5721 | |||
| 5722 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3627 times.
|
3627 | if (dict == NULL) |
| 5723 | ✗ | goto error; | |
| 5724 | |||
| 5725 | /* Merge in attrs reachable from its class. */ | ||
| 5726 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 3627 times.
|
3627 | if (_PyObject_LookupAttr(self, &_Py_ID(__class__), &itsclass) < 0) { |
| 5727 | ✗ | goto error; | |
| 5728 | } | ||
| 5729 | /* XXX(tomer): Perhaps fall back to Py_TYPE(obj) if no | ||
| 5730 | __class__ exists? */ | ||
| 5731 |
2/4✓ Branch 0 taken 3627 times.
✗ Branch 1 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 3627 times.
|
3627 | if (itsclass != NULL && merge_class_dict(dict, itsclass) < 0) |
| 5732 | ✗ | goto error; | |
| 5733 | |||
| 5734 | 3627 | result = PyDict_Keys(dict); | |
| 5735 | /* fall through */ | ||
| 5736 | 3627 | error: | |
| 5737 | 3627 | Py_XDECREF(itsclass); | |
| 5738 | 3627 | Py_XDECREF(dict); | |
| 5739 | 3627 | return result; | |
| 5740 | } | ||
| 5741 | |||
| 5742 | static PyMethodDef object_methods[] = { | ||
| 5743 | OBJECT___REDUCE_EX___METHODDEF | ||
| 5744 | OBJECT___REDUCE___METHODDEF | ||
| 5745 | OBJECT___GETSTATE___METHODDEF | ||
| 5746 | {"__subclasshook__", object_subclasshook, METH_CLASS | METH_VARARGS, | ||
| 5747 | object_subclasshook_doc}, | ||
| 5748 | {"__init_subclass__", object_init_subclass, METH_CLASS | METH_NOARGS, | ||
| 5749 | object_init_subclass_doc}, | ||
| 5750 | OBJECT___FORMAT___METHODDEF | ||
| 5751 | OBJECT___SIZEOF___METHODDEF | ||
| 5752 | OBJECT___DIR___METHODDEF | ||
| 5753 | {0} | ||
| 5754 | }; | ||
| 5755 | |||
| 5756 | PyDoc_STRVAR(object_doc, | ||
| 5757 | "object()\n--\n\n" | ||
| 5758 | "The base class of the class hierarchy.\n\n" | ||
| 5759 | "When called, it accepts no arguments and returns a new featureless\n" | ||
| 5760 | "instance that has no instance attributes and cannot be given any.\n"); | ||
| 5761 | |||
| 5762 | PyTypeObject PyBaseObject_Type = { | ||
| 5763 | PyVarObject_HEAD_INIT(&PyType_Type, 0) | ||
| 5764 | "object", /* tp_name */ | ||
| 5765 | sizeof(PyObject), /* tp_basicsize */ | ||
| 5766 | 0, /* tp_itemsize */ | ||
| 5767 | object_dealloc, /* tp_dealloc */ | ||
| 5768 | 0, /* tp_vectorcall_offset */ | ||
| 5769 | 0, /* tp_getattr */ | ||
| 5770 | 0, /* tp_setattr */ | ||
| 5771 | 0, /* tp_as_async */ | ||
| 5772 | object_repr, /* tp_repr */ | ||
| 5773 | 0, /* tp_as_number */ | ||
| 5774 | 0, /* tp_as_sequence */ | ||
| 5775 | 0, /* tp_as_mapping */ | ||
| 5776 | (hashfunc)_Py_HashPointer, /* tp_hash */ | ||
| 5777 | 0, /* tp_call */ | ||
| 5778 | object_str, /* tp_str */ | ||
| 5779 | PyObject_GenericGetAttr, /* tp_getattro */ | ||
| 5780 | PyObject_GenericSetAttr, /* tp_setattro */ | ||
| 5781 | 0, /* tp_as_buffer */ | ||
| 5782 | Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ | ||
| 5783 | object_doc, /* tp_doc */ | ||
| 5784 | 0, /* tp_traverse */ | ||
| 5785 | 0, /* tp_clear */ | ||
| 5786 | object_richcompare, /* tp_richcompare */ | ||
| 5787 | 0, /* tp_weaklistoffset */ | ||
| 5788 | 0, /* tp_iter */ | ||
| 5789 | 0, /* tp_iternext */ | ||
| 5790 | object_methods, /* tp_methods */ | ||
| 5791 | 0, /* tp_members */ | ||
| 5792 | object_getsets, /* tp_getset */ | ||
| 5793 | 0, /* tp_base */ | ||
| 5794 | 0, /* tp_dict */ | ||
| 5795 | 0, /* tp_descr_get */ | ||
| 5796 | 0, /* tp_descr_set */ | ||
| 5797 | 0, /* tp_dictoffset */ | ||
| 5798 | object_init, /* tp_init */ | ||
| 5799 | PyType_GenericAlloc, /* tp_alloc */ | ||
| 5800 | object_new, /* tp_new */ | ||
| 5801 | PyObject_Del, /* tp_free */ | ||
| 5802 | }; | ||
| 5803 | |||
| 5804 | |||
| 5805 | static int | ||
| 5806 | 3129857 | type_add_method(PyTypeObject *type, PyMethodDef *meth) | |
| 5807 | { | ||
| 5808 | PyObject *descr; | ||
| 5809 | 3129857 | int isdescr = 1; | |
| 5810 |
2/2✓ Branch 0 taken 124702 times.
✓ Branch 1 taken 3005155 times.
|
3129857 | if (meth->ml_flags & METH_CLASS) { |
| 5811 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 124702 times.
|
124702 | if (meth->ml_flags & METH_STATIC) { |
| 5812 | ✗ | PyErr_SetString(PyExc_ValueError, | |
| 5813 | "method cannot be both class and static"); | ||
| 5814 | ✗ | return -1; | |
| 5815 | } | ||
| 5816 | 124702 | descr = PyDescr_NewClassMethod(type, meth); | |
| 5817 | } | ||
| 5818 |
2/2✓ Branch 0 taken 10230 times.
✓ Branch 1 taken 2994925 times.
|
3005155 | else if (meth->ml_flags & METH_STATIC) { |
| 5819 | 10230 | PyObject *cfunc = PyCFunction_NewEx(meth, (PyObject*)type, NULL); | |
| 5820 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 10230 times.
|
10230 | if (cfunc == NULL) { |
| 5821 | ✗ | return -1; | |
| 5822 | } | ||
| 5823 | 10230 | descr = PyStaticMethod_New(cfunc); | |
| 5824 | 10230 | isdescr = 0; // PyStaticMethod is not PyDescrObject | |
| 5825 | 10230 | Py_DECREF(cfunc); | |
| 5826 | } | ||
| 5827 | else { | ||
| 5828 | 2994925 | descr = PyDescr_NewMethod(type, meth); | |
| 5829 | } | ||
| 5830 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3129857 times.
|
3129857 | if (descr == NULL) { |
| 5831 | ✗ | return -1; | |
| 5832 | } | ||
| 5833 | |||
| 5834 | PyObject *name; | ||
| 5835 |
2/2✓ Branch 0 taken 3119627 times.
✓ Branch 1 taken 10230 times.
|
3129857 | if (isdescr) { |
| 5836 | 3119627 | name = PyDescr_NAME(descr); | |
| 5837 | } | ||
| 5838 | else { | ||
| 5839 | 10230 | name = PyUnicode_FromString(meth->ml_name); | |
| 5840 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 10230 times.
|
10230 | if (name == NULL) { |
| 5841 | ✗ | Py_DECREF(descr); | |
| 5842 | ✗ | return -1; | |
| 5843 | } | ||
| 5844 | } | ||
| 5845 | |||
| 5846 | int err; | ||
| 5847 |
2/2✓ Branch 0 taken 3112817 times.
✓ Branch 1 taken 17040 times.
|
3129857 | if (!(meth->ml_flags & METH_COEXIST)) { |
| 5848 | 3112817 | err = PyDict_SetDefault(type->tp_dict, name, descr) == NULL; | |
| 5849 | } | ||
| 5850 | else { | ||
| 5851 | 17040 | err = PyDict_SetItem(type->tp_dict, name, descr) < 0; | |
| 5852 | } | ||
| 5853 |
2/2✓ Branch 0 taken 10230 times.
✓ Branch 1 taken 3119627 times.
|
3129857 | if (!isdescr) { |
| 5854 | 10230 | Py_DECREF(name); | |
| 5855 | } | ||
| 5856 | 3129857 | Py_DECREF(descr); | |
| 5857 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3129857 times.
|
3129857 | if (err) { |
| 5858 | ✗ | return -1; | |
| 5859 | } | ||
| 5860 | 3129857 | return 0; | |
| 5861 | } | ||
| 5862 | |||
| 5863 | |||
| 5864 | /* Add the methods from tp_methods to the __dict__ in a type object */ | ||
| 5865 | static int | ||
| 5866 | 2484676 | type_add_methods(PyTypeObject *type) | |
| 5867 | { | ||
| 5868 | 2484676 | PyMethodDef *meth = type->tp_methods; | |
| 5869 |
2/2✓ Branch 0 taken 1912305 times.
✓ Branch 1 taken 572371 times.
|
2484676 | if (meth == NULL) { |
| 5870 | 1912305 | return 0; | |
| 5871 | } | ||
| 5872 | |||
| 5873 |
2/2✓ Branch 0 taken 3129857 times.
✓ Branch 1 taken 572371 times.
|
3702228 | for (; meth->ml_name != NULL; meth++) { |
| 5874 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 3129857 times.
|
3129857 | if (type_add_method(type, meth) < 0) { |
| 5875 | ✗ | return -1; | |
| 5876 | } | ||
| 5877 | } | ||
| 5878 | 572371 | return 0; | |
| 5879 | } | ||
| 5880 | |||
| 5881 | |||
| 5882 | static int | ||
| 5883 | 2484676 | type_add_members(PyTypeObject *type) | |
| 5884 | { | ||
| 5885 | 2484676 | PyMemberDef *memb = type->tp_members; | |
| 5886 |
2/2✓ Branch 0 taken 606245 times.
✓ Branch 1 taken 1878431 times.
|
2484676 | if (memb == NULL) { |
| 5887 | 606245 | return 0; | |
| 5888 | } | ||
| 5889 | |||
| 5890 | 1878431 | PyObject *dict = type->tp_dict; | |
| 5891 |
2/2✓ Branch 0 taken 1310872 times.
✓ Branch 1 taken 1878431 times.
|
3189303 | for (; memb->name != NULL; memb++) { |
| 5892 | 1310872 | PyObject *descr = PyDescr_NewMember(type, memb); | |
| 5893 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1310872 times.
|
1310872 | if (descr == NULL) |
| 5894 | ✗ | return -1; | |
| 5895 | |||
| 5896 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 1310872 times.
|
1310872 | if (PyDict_SetDefault(dict, PyDescr_NAME(descr), descr) == NULL) { |
| 5897 | ✗ | Py_DECREF(descr); | |
| 5898 | ✗ | return -1; | |
| 5899 | } | ||
| 5900 | 1310872 | Py_DECREF(descr); | |
| 5901 | } | ||
| 5902 | 1878431 | return 0; | |
| 5903 | } | ||
| 5904 | |||
| 5905 | |||
| 5906 | static int | ||
| 5907 | 2484676 | type_add_getset(PyTypeObject *type) | |
| 5908 | { | ||
| 5909 | 2484676 | PyGetSetDef *gsp = type->tp_getset; | |
| 5910 |
2/2✓ Branch 0 taken 1618892 times.
✓ Branch 1 taken 865784 times.
|
2484676 | if (gsp == NULL) { |
| 5911 | 1618892 | return 0; | |
| 5912 | } | ||
| 5913 | |||
| 5914 | 865784 | PyObject *dict = type->tp_dict; | |
| 5915 |
2/2✓ Branch 0 taken 1758332 times.
✓ Branch 1 taken 865784 times.
|
2624116 | for (; gsp->name != NULL; gsp++) { |
| 5916 | 1758332 | PyObject *descr = PyDescr_NewGetSet(type, gsp); | |
| 5917 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1758332 times.
|
1758332 | if (descr == NULL) { |
| 5918 | ✗ | return -1; | |
| 5919 | } | ||
| 5920 | |||
| 5921 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 1758332 times.
|
1758332 | if (PyDict_SetDefault(dict, PyDescr_NAME(descr), descr) == NULL) { |
| 5922 | ✗ | Py_DECREF(descr); | |
| 5923 | ✗ | return -1; | |
| 5924 | } | ||
| 5925 | 1758332 | Py_DECREF(descr); | |
| 5926 | } | ||
| 5927 | 865784 | return 0; | |
| 5928 | } | ||
| 5929 | |||
| 5930 | |||
| 5931 | static void | ||
| 5932 | 2481268 | inherit_special(PyTypeObject *type, PyTypeObject *base) | |
| 5933 | { | ||
| 5934 | /* Copying tp_traverse and tp_clear is connected to the GC flags */ | ||
| 5935 |
2/2✓ Branch 0 taken 174235 times.
✓ Branch 1 taken 2307033 times.
|
2481268 | if (!(type->tp_flags & Py_TPFLAGS_HAVE_GC) && |
| 5936 |
2/2✓ Branch 0 taken 27106 times.
✓ Branch 1 taken 147129 times.
|
174235 | (base->tp_flags & Py_TPFLAGS_HAVE_GC) && |
| 5937 |
2/4✓ Branch 0 taken 27106 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 27106 times.
✗ Branch 3 not taken.
|
27106 | (!type->tp_traverse && !type->tp_clear)) { |
| 5938 | 27106 | type->tp_flags |= Py_TPFLAGS_HAVE_GC; | |
| 5939 |
1/2✓ Branch 0 taken 27106 times.
✗ Branch 1 not taken.
|
27106 | if (type->tp_traverse == NULL) |
| 5940 | 27106 | type->tp_traverse = base->tp_traverse; | |
| 5941 |
1/2✓ Branch 0 taken 27106 times.
✗ Branch 1 not taken.
|
27106 | if (type->tp_clear == NULL) |
| 5942 | 27106 | type->tp_clear = base->tp_clear; | |
| 5943 | } | ||
| 5944 | 2481268 | type->tp_flags |= (base->tp_flags & Py_TPFLAGS_MANAGED_DICT); | |
| 5945 | |||
| 5946 |
2/2✓ Branch 0 taken 32434 times.
✓ Branch 1 taken 2448834 times.
|
2481268 | if (type->tp_basicsize == 0) |
| 5947 | 32434 | type->tp_basicsize = base->tp_basicsize; | |
| 5948 | |||
| 5949 | /* Copy other non-function slots */ | ||
| 5950 | |||
| 5951 | #define COPYVAL(SLOT) \ | ||
| 5952 | if (type->SLOT == 0) { type->SLOT = base->SLOT; } | ||
| 5953 | |||
| 5954 |
2/2✓ Branch 0 taken 2207492 times.
✓ Branch 1 taken 273776 times.
|
2481268 | COPYVAL(tp_itemsize); |
| 5955 |
2/2✓ Branch 0 taken 1727439 times.
✓ Branch 1 taken 753829 times.
|
2481268 | COPYVAL(tp_weaklistoffset); |
| 5956 |
2/2✓ Branch 0 taken 1683290 times.
✓ Branch 1 taken 797978 times.
|
2481268 | COPYVAL(tp_dictoffset); |
| 5957 | #undef COPYVAL | ||
| 5958 | |||
| 5959 | /* Setup fast subclass flags */ | ||
| 5960 |
2/2✓ Branch 1 taken 441203 times.
✓ Branch 2 taken 2040065 times.
|
2481268 | if (PyType_IsSubtype(base, (PyTypeObject*)PyExc_BaseException)) { |
| 5961 | 441203 | type->tp_flags |= Py_TPFLAGS_BASE_EXC_SUBCLASS; | |
| 5962 | } | ||
| 5963 |
2/2✓ Branch 1 taken 14905 times.
✓ Branch 2 taken 2025160 times.
|
2040065 | else if (PyType_IsSubtype(base, &PyType_Type)) { |
| 5964 | 14905 | type->tp_flags |= Py_TPFLAGS_TYPE_SUBCLASS; | |
| 5965 | } | ||
| 5966 |
2/2✓ Branch 1 taken 42014 times.
✓ Branch 2 taken 1983146 times.
|
2025160 | else if (PyType_IsSubtype(base, &PyLong_Type)) { |
| 5967 | 42014 | type->tp_flags |= Py_TPFLAGS_LONG_SUBCLASS; | |
| 5968 | } | ||
| 5969 |
2/2✓ Branch 1 taken 182 times.
✓ Branch 2 taken 1982964 times.
|
1983146 | else if (PyType_IsSubtype(base, &PyBytes_Type)) { |
| 5970 | 182 | type->tp_flags |= Py_TPFLAGS_BYTES_SUBCLASS; | |
| 5971 | } | ||
| 5972 |
2/2✓ Branch 1 taken 9420 times.
✓ Branch 2 taken 1973544 times.
|
1982964 | else if (PyType_IsSubtype(base, &PyUnicode_Type)) { |
| 5973 | 9420 | type->tp_flags |= Py_TPFLAGS_UNICODE_SUBCLASS; | |
| 5974 | } | ||
| 5975 |
2/2✓ Branch 1 taken 176734 times.
✓ Branch 2 taken 1796810 times.
|
1973544 | else if (PyType_IsSubtype(base, &PyTuple_Type)) { |
| 5976 | 176734 | type->tp_flags |= Py_TPFLAGS_TUPLE_SUBCLASS; | |
| 5977 | } | ||
| 5978 |
2/2✓ Branch 1 taken 8193 times.
✓ Branch 2 taken 1788617 times.
|
1796810 | else if (PyType_IsSubtype(base, &PyList_Type)) { |
| 5979 | 8193 | type->tp_flags |= Py_TPFLAGS_LIST_SUBCLASS; | |
| 5980 | } | ||
| 5981 |
2/2✓ Branch 1 taken 18812 times.
✓ Branch 2 taken 1769805 times.
|
1788617 | else if (PyType_IsSubtype(base, &PyDict_Type)) { |
| 5982 | 18812 | type->tp_flags |= Py_TPFLAGS_DICT_SUBCLASS; | |
| 5983 | } | ||
| 5984 |
2/2✓ Branch 1 taken 256016 times.
✓ Branch 2 taken 2225252 times.
|
2481268 | if (PyType_HasFeature(base, _Py_TPFLAGS_MATCH_SELF)) { |
| 5985 | 256016 | type->tp_flags |= _Py_TPFLAGS_MATCH_SELF; | |
| 5986 | } | ||
| 5987 | 2481268 | } | |
| 5988 | |||
| 5989 | static int | ||
| 5990 | 2464791 | overrides_hash(PyTypeObject *type) | |
| 5991 | { | ||
| 5992 | 2464791 | PyObject *dict = type->tp_dict; | |
| 5993 | |||
| 5994 | assert(dict != NULL); | ||
| 5995 | 2464791 | int r = PyDict_Contains(dict, &_Py_ID(__eq__)); | |
| 5996 |
2/2✓ Branch 0 taken 2256871 times.
✓ Branch 1 taken 207920 times.
|
2464791 | if (r == 0) { |
| 5997 | 2256871 | r = PyDict_Contains(dict, &_Py_ID(__hash__)); | |
| 5998 | } | ||
| 5999 | 2464791 | return r; | |
| 6000 | } | ||
| 6001 | |||
| 6002 | static int | ||
| 6003 | 6382692 | inherit_slots(PyTypeObject *type, PyTypeObject *base) | |
| 6004 | { | ||
| 6005 | PyTypeObject *basebase; | ||
| 6006 | |||
| 6007 | #undef SLOTDEFINED | ||
| 6008 | #undef COPYSLOT | ||
| 6009 | #undef COPYNUM | ||
| 6010 | #undef COPYSEQ | ||
| 6011 | #undef COPYMAP | ||
| 6012 | #undef COPYBUF | ||
| 6013 | |||
| 6014 | #define SLOTDEFINED(SLOT) \ | ||
| 6015 | (base->SLOT != 0 && \ | ||
| 6016 | (basebase == NULL || base->SLOT != basebase->SLOT)) | ||
| 6017 | |||
| 6018 | #define COPYSLOT(SLOT) \ | ||
| 6019 | if (!type->SLOT && SLOTDEFINED(SLOT)) type->SLOT = base->SLOT | ||
| 6020 | |||
| 6021 | #define COPYASYNC(SLOT) COPYSLOT(tp_as_async->SLOT) | ||
| 6022 | #define COPYNUM(SLOT) COPYSLOT(tp_as_number->SLOT) | ||
| 6023 | #define COPYSEQ(SLOT) COPYSLOT(tp_as_sequence->SLOT) | ||
| 6024 | #define COPYMAP(SLOT) COPYSLOT(tp_as_mapping->SLOT) | ||
| 6025 | #define COPYBUF(SLOT) COPYSLOT(tp_as_buffer->SLOT) | ||
| 6026 | |||
| 6027 | /* This won't inherit indirect slots (from tp_as_number etc.) | ||
| 6028 | if type doesn't provide the space. */ | ||
| 6029 | |||
| 6030 |
4/4✓ Branch 0 taken 4995946 times.
✓ Branch 1 taken 1386746 times.
✓ Branch 2 taken 2398258 times.
✓ Branch 3 taken 2597688 times.
|
6382692 | if (type->tp_as_number != NULL && base->tp_as_number != NULL) { |
| 6031 | 2398258 | basebase = base->tp_base; | |
| 6032 |
2/2✓ Branch 0 taken 1274345 times.
✓ Branch 1 taken 1123913 times.
|
2398258 | if (basebase->tp_as_number == NULL) |
| 6033 | 1274345 | basebase = NULL; | |
| 6034 |
8/8✓ Branch 0 taken 1885028 times.
✓ Branch 1 taken 513230 times.
✓ Branch 2 taken 219909 times.
✓ Branch 3 taken 1665119 times.
✓ Branch 4 taken 173342 times.
✓ Branch 5 taken 46567 times.
✓ Branch 6 taken 70012 times.
✓ Branch 7 taken 103330 times.
|
2398258 | COPYNUM(nb_add); |
| 6035 |
8/8✓ Branch 0 taken 1823121 times.
✓ Branch 1 taken 575137 times.
✓ Branch 2 taken 229107 times.
✓ Branch 3 taken 1594014 times.
✓ Branch 4 taken 183461 times.
✓ Branch 5 taken 45646 times.
✓ Branch 6 taken 81105 times.
✓ Branch 7 taken 102356 times.
|
2398258 | COPYNUM(nb_subtract); |
| 6036 |
8/8✓ Branch 0 taken 1892062 times.
✓ Branch 1 taken 506196 times.
✓ Branch 2 taken 213255 times.
✓ Branch 3 taken 1678807 times.
✓ Branch 4 taken 169113 times.
✓ Branch 5 taken 44142 times.
✓ Branch 6 taken 66433 times.
✓ Branch 7 taken 102680 times.
|
2398258 | COPYNUM(nb_multiply); |
| 6037 |
8/8✓ Branch 0 taken 1905752 times.
✓ Branch 1 taken 492506 times.
✓ Branch 2 taken 172196 times.
✓ Branch 3 taken 1733556 times.
✓ Branch 4 taken 120237 times.
✓ Branch 5 taken 51959 times.
✓ Branch 6 taken 43613 times.
✓ Branch 7 taken 76624 times.
|
2398258 | COPYNUM(nb_remainder); |
| 6038 |
8/8✓ Branch 0 taken 2184666 times.
✓ Branch 1 taken 213592 times.
✓ Branch 2 taken 127598 times.
✓ Branch 3 taken 2057068 times.
✓ Branch 4 taken 85351 times.
✓ Branch 5 taken 42247 times.
✓ Branch 6 taken 32164 times.
✓ Branch 7 taken 53187 times.
|
2398258 | COPYNUM(nb_divmod); |
| 6039 |
8/8✓ Branch 0 taken 2150787 times.
✓ Branch 1 taken 247471 times.
✓ Branch 2 taken 154194 times.
✓ Branch 3 taken 1996593 times.
✓ Branch 4 taken 111157 times.
✓ Branch 5 taken 43037 times.
✓ Branch 6 taken 42489 times.
✓ Branch 7 taken 68668 times.
|
2398258 | COPYNUM(nb_power); |
| 6040 |
8/8✓ Branch 0 taken 1922012 times.
✓ Branch 1 taken 476246 times.
✓ Branch 2 taken 167511 times.
✓ Branch 3 taken 1754501 times.
✓ Branch 4 taken 124389 times.
✓ Branch 5 taken 43122 times.
✓ Branch 6 taken 46983 times.
✓ Branch 7 taken 77406 times.
|
2398258 | COPYNUM(nb_negative); |
| 6041 |
8/8✓ Branch 0 taken 2187714 times.
✓ Branch 1 taken 210544 times.
✓ Branch 2 taken 136068 times.
✓ Branch 3 taken 2051646 times.
✓ Branch 4 taken 93226 times.
✓ Branch 5 taken 42842 times.
✓ Branch 6 taken 34429 times.
✓ Branch 7 taken 58797 times.
|
2398258 | COPYNUM(nb_positive); |
| 6042 |
8/8✓ Branch 0 taken 2180462 times.
✓ Branch 1 taken 217796 times.
✓ Branch 2 taken 143592 times.
✓ Branch 3 taken 2036870 times.
✓ Branch 4 taken 101005 times.
✓ Branch 5 taken 42587 times.
✓ Branch 6 taken 35493 times.
✓ Branch 7 taken 65512 times.
|
2398258 | COPYNUM(nb_absolute); |
| 6043 |
8/8✓ Branch 0 taken 2003566 times.
✓ Branch 1 taken 394692 times.
✓ Branch 2 taken 123221 times.
✓ Branch 3 taken 1880345 times.
✓ Branch 4 taken 72283 times.
✓ Branch 5 taken 50938 times.
✓ Branch 6 taken 19414 times.
✓ Branch 7 taken 52869 times.
|
2398258 | COPYNUM(nb_bool); |
| 6044 |
8/8✓ Branch 0 taken 1983262 times.
✓ Branch 1 taken 414996 times.
✓ Branch 2 taken 130263 times.
✓ Branch 3 taken 1852999 times.
✓ Branch 4 taken 94256 times.
✓ Branch 5 taken 36007 times.
✓ Branch 6 taken 34534 times.
✓ Branch 7 taken 59722 times.
|
2398258 | COPYNUM(nb_invert); |
| 6045 |
8/8✓ Branch 0 taken 2065111 times.
✓ Branch 1 taken 333147 times.
✓ Branch 2 taken 95911 times.
✓ Branch 3 taken 1969200 times.
✓ Branch 4 taken 53897 times.
✓ Branch 5 taken 42014 times.
✓ Branch 6 taken 10018 times.
✓ Branch 7 taken 43879 times.
|
2398258 | COPYNUM(nb_lshift); |
| 6046 |
8/8✓ Branch 0 taken 2065111 times.
✓ Branch 1 taken 333147 times.
✓ Branch 2 taken 95911 times.
✓ Branch 3 taken 1969200 times.
✓ Branch 4 taken 53897 times.
✓ Branch 5 taken 42014 times.
✓ Branch 6 taken 10018 times.
✓ Branch 7 taken 43879 times.
|
2398258 | COPYNUM(nb_rshift); |
| 6047 |
8/8✓ Branch 0 taken 1941980 times.
✓ Branch 1 taken 456278 times.
✓ Branch 2 taken 151630 times.
✓ Branch 3 taken 1790350 times.
✓ Branch 4 taken 118260 times.
✓ Branch 5 taken 33370 times.
✓ Branch 6 taken 55687 times.
✓ Branch 7 taken 62573 times.
|
2398258 | COPYNUM(nb_and); |
| 6048 |
8/8✓ Branch 0 taken 2200670 times.
✓ Branch 1 taken 197588 times.
✓ Branch 2 taken 123937 times.
✓ Branch 3 taken 2076733 times.
✓ Branch 4 taken 91790 times.
✓ Branch 5 taken 32147 times.
✓ Branch 6 taken 42495 times.
✓ Branch 7 taken 49295 times.
|
2398258 | COPYNUM(nb_xor); |
| 6049 |
8/8✓ Branch 0 taken 1920381 times.
✓ Branch 1 taken 477877 times.
✓ Branch 2 taken 192518 times.
✓ Branch 3 taken 1727863 times.
✓ Branch 4 taken 129271 times.
✓ Branch 5 taken 63247 times.
✓ Branch 6 taken 62058 times.
✓ Branch 7 taken 67213 times.
|
2398258 | COPYNUM(nb_or); |
| 6050 |
8/8✓ Branch 0 taken 2193841 times.
✓ Branch 1 taken 204417 times.
✓ Branch 2 taken 119962 times.
✓ Branch 3 taken 2073879 times.
✓ Branch 4 taken 77460 times.
✓ Branch 5 taken 42502 times.
✓ Branch 6 taken 27724 times.
✓ Branch 7 taken 49736 times.
|
2398258 | COPYNUM(nb_int); |
| 6051 |
8/8✓ Branch 0 taken 2185001 times.
✓ Branch 1 taken 213257 times.
✓ Branch 2 taken 128003 times.
✓ Branch 3 taken 2056998 times.
✓ Branch 4 taken 85501 times.
✓ Branch 5 taken 42502 times.
✓ Branch 6 taken 32144 times.
✓ Branch 7 taken 53357 times.
|
2398258 | COPYNUM(nb_float); |
| 6052 |
8/8✓ Branch 0 taken 2383384 times.
✓ Branch 1 taken 14874 times.
✓ Branch 2 taken 4729 times.
✓ Branch 3 taken 2378655 times.
✓ Branch 4 taken 2889 times.
✓ Branch 5 taken 1840 times.
✓ Branch 6 taken 2479 times.
✓ Branch 7 taken 410 times.
|
2398258 | COPYNUM(nb_inplace_add); |
| 6053 |
7/8✓ Branch 0 taken 2397677 times.
✓ Branch 1 taken 581 times.
✓ Branch 2 taken 529 times.
✓ Branch 3 taken 2397148 times.
✓ Branch 4 taken 145 times.
✓ Branch 5 taken 384 times.
✓ Branch 6 taken 145 times.
✗ Branch 7 not taken.
|
2398258 | COPYNUM(nb_inplace_subtract); |
| 6054 |
6/8✓ Branch 0 taken 2398104 times.
✓ Branch 1 taken 154 times.
✓ Branch 2 taken 22 times.
✓ Branch 3 taken 2398082 times.
✓ Branch 4 taken 22 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 22 times.
✗ Branch 7 not taken.
|
2398258 | COPYNUM(nb_inplace_multiply); |
| 6055 |
2/8✓ Branch 0 taken 2398258 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2398258 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
|
2398258 | COPYNUM(nb_inplace_remainder); |
| 6056 |
2/8✓ Branch 0 taken 2398258 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2398258 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
|
2398258 | COPYNUM(nb_inplace_power); |
| 6057 |
2/8✓ Branch 0 taken 2398258 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2398258 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
|
2398258 | COPYNUM(nb_inplace_lshift); |
| 6058 |
2/8✓ Branch 0 taken 2398258 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2398258 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
|
2398258 | COPYNUM(nb_inplace_rshift); |
| 6059 |
7/8✓ Branch 0 taken 2397677 times.
✓ Branch 1 taken 581 times.
✓ Branch 2 taken 529 times.
✓ Branch 3 taken 2397148 times.
✓ Branch 4 taken 145 times.
✓ Branch 5 taken 384 times.
✓ Branch 6 taken 145 times.
✗ Branch 7 not taken.
|
2398258 | COPYNUM(nb_inplace_and); |
| 6060 |
7/8✓ Branch 0 taken 2397677 times.
✓ Branch 1 taken 581 times.
✓ Branch 2 taken 529 times.
✓ Branch 3 taken 2397148 times.
✓ Branch 4 taken 145 times.
✓ Branch 5 taken 384 times.
✓ Branch 6 taken 145 times.
✗ Branch 7 not taken.
|
2398258 | COPYNUM(nb_inplace_xor); |
| 6061 |
8/8✓ Branch 0 taken 2393181 times.
✓ Branch 1 taken 5077 times.
✓ Branch 2 taken 16619 times.
✓ Branch 3 taken 2376562 times.
✓ Branch 4 taken 1328 times.
✓ Branch 5 taken 15291 times.
✓ Branch 6 taken 489 times.
✓ Branch 7 taken 839 times.
|
2398258 | COPYNUM(nb_inplace_or); |
| 6062 |
8/8✓ Branch 0 taken 1909873 times.
✓ Branch 1 taken 488385 times.
✓ Branch 2 taken 181658 times.
✓ Branch 3 taken 1728215 times.
✓ Branch 4 taken 135741 times.
✓ Branch 5 taken 45917 times.
✓ Branch 6 taken 51055 times.
✓ Branch 7 taken 84686 times.
|
2398258 | COPYNUM(nb_true_divide); |
| 6063 |
8/8✓ Branch 0 taken 2184666 times.
✓ Branch 1 taken 213592 times.
✓ Branch 2 taken 127598 times.
✓ Branch 3 taken 2057068 times.
✓ Branch 4 taken 85351 times.
✓ Branch 5 taken 42247 times.
✓ Branch 6 taken 32164 times.
✓ Branch 7 taken 53187 times.
|
2398258 | COPYNUM(nb_floor_divide); |
| 6064 |
2/8✓ Branch 0 taken 2398258 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2398258 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
|
2398258 | COPYNUM(nb_inplace_true_divide); |
| 6065 |
2/8✓ Branch 0 taken 2398258 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2398258 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
|
2398258 | COPYNUM(nb_inplace_floor_divide); |
| 6066 |
8/8✓ Branch 0 taken 2314028 times.
✓ Branch 1 taken 84230 times.
✓ Branch 2 taken 73756 times.
✓ Branch 3 taken 2240272 times.
✓ Branch 4 taken 31742 times.
✓ Branch 5 taken 42014 times.
✓ Branch 6 taken 340 times.
✓ Branch 7 taken 31402 times.
|
2398258 | COPYNUM(nb_index); |
| 6067 |
8/8✓ Branch 0 taken 2381683 times.
✓ Branch 1 taken 16575 times.
✓ Branch 2 taken 10880 times.
✓ Branch 3 taken 2370803 times.
✓ Branch 4 taken 10625 times.
✓ Branch 5 taken 255 times.
✓ Branch 6 taken 3400 times.
✓ Branch 7 taken 7225 times.
|
2398258 | COPYNUM(nb_matrix_multiply); |
| 6068 |
2/8✓ Branch 0 taken 2398258 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2398258 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
|
2398258 | COPYNUM(nb_inplace_matrix_multiply); |
| 6069 | } | ||
| 6070 | |||
| 6071 |
4/4✓ Branch 0 taken 4917211 times.
✓ Branch 1 taken 1465481 times.
✓ Branch 2 taken 2300829 times.
✓ Branch 3 taken 2616382 times.
|
6382692 | if (type->tp_as_async != NULL && base->tp_as_async != NULL) { |
| 6072 | 2300829 | basebase = base->tp_base; | |
| 6073 |
2/2✓ Branch 0 taken 1217551 times.
✓ Branch 1 taken 1083278 times.
|
2300829 | if (basebase->tp_as_async == NULL) |
| 6074 | 1217551 | basebase = NULL; | |
| 6075 |
5/8✓ Branch 0 taken 2300463 times.
✓ Branch 1 taken 366 times.
✓ Branch 2 taken 3673 times.
✓ Branch 3 taken 2296790 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 3673 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
|
2300829 | COPYASYNC(am_await); |
| 6076 |
6/8✓ Branch 0 taken 2300829 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 8823 times.
✓ Branch 3 taken 2292006 times.
✓ Branch 4 taken 2941 times.
✓ Branch 5 taken 5882 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 2941 times.
|
2300829 | COPYASYNC(am_aiter); |
| 6077 |
6/8✓ Branch 0 taken 2297888 times.
✓ Branch 1 taken 2941 times.
✓ Branch 2 taken 2941 times.
✓ Branch 3 taken 2294947 times.
✓ Branch 4 taken 2941 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 2941 times.
✗ Branch 7 not taken.
|
2300829 | COPYASYNC(am_anext); |
| 6078 | } | ||
| 6079 | |||
| 6080 |
4/4✓ Branch 0 taken 4963195 times.
✓ Branch 1 taken 1419497 times.
✓ Branch 2 taken 2479962 times.
✓ Branch 3 taken 2483233 times.
|
6382692 | if (type->tp_as_sequence != NULL && base->tp_as_sequence != NULL) { |
| 6081 | 2479962 | basebase = base->tp_base; | |
| 6082 |
2/2✓ Branch 0 taken 1378168 times.
✓ Branch 1 taken 1101794 times.
|
2479962 | if (basebase->tp_as_sequence == NULL) |
| 6083 | 1378168 | basebase = NULL; | |
| 6084 |
8/8✓ Branch 0 taken 2259569 times.
✓ Branch 1 taken 220393 times.
✓ Branch 2 taken 404699 times.
✓ Branch 3 taken 1854870 times.
✓ Branch 4 taken 173053 times.
✓ Branch 5 taken 231646 times.
✓ Branch 6 taken 16877 times.
✓ Branch 7 taken 156176 times.
|
2479962 | COPYSEQ(sq_length); |
| 6085 |
7/8✓ Branch 0 taken 2457322 times.
✓ Branch 1 taken 22640 times.
✓ Branch 2 taken 183665 times.
✓ Branch 3 taken 2273657 times.
✓ Branch 4 taken 18220 times.
✓ Branch 5 taken 165445 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 18220 times.
|
2479962 | COPYSEQ(sq_concat); |
| 6086 |
7/8✓ Branch 0 taken 2457322 times.
✓ Branch 1 taken 22640 times.
✓ Branch 2 taken 184207 times.
✓ Branch 3 taken 2273115 times.
✓ Branch 4 taken 18280 times.
✓ Branch 5 taken 165927 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 18280 times.
|
2479962 | COPYSEQ(sq_repeat); |
| 6087 |
8/8✓ Branch 0 taken 2013079 times.
✓ Branch 1 taken 466883 times.
✓ Branch 2 taken 323768 times.
✓ Branch 3 taken 1689311 times.
✓ Branch 4 taken 162561 times.
✓ Branch 5 taken 161207 times.
✓ Branch 6 taken 82405 times.
✓ Branch 7 taken 80156 times.
|
2479962 | COPYSEQ(sq_item); |
| 6088 |
8/8✓ Branch 0 taken 2385284 times.
✓ Branch 1 taken 94678 times.
✓ Branch 2 taken 30527 times.
✓ Branch 3 taken 2354757 times.
✓ Branch 4 taken 21071 times.
✓ Branch 5 taken 9456 times.
✓ Branch 6 taken 19064 times.
✓ Branch 7 taken 2007 times.
|
2479962 | COPYSEQ(sq_ass_item); |
| 6089 |
8/8✓ Branch 0 taken 1951415 times.
✓ Branch 1 taken 528547 times.
✓ Branch 2 taken 355774 times.
✓ Branch 3 taken 1595641 times.
✓ Branch 4 taken 162783 times.
✓ Branch 5 taken 192991 times.
✓ Branch 6 taken 75838 times.
✓ Branch 7 taken 86945 times.
|
2479962 | COPYSEQ(sq_contains); |
| 6090 |
7/8✓ Branch 0 taken 2479667 times.
✓ Branch 1 taken 295 times.
✓ Branch 2 taken 10328 times.
✓ Branch 3 taken 2469339 times.
✓ Branch 4 taken 2136 times.
✓ Branch 5 taken 8192 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 2136 times.
|
2479962 | COPYSEQ(sq_inplace_concat); |
| 6091 |
7/8✓ Branch 0 taken 2479667 times.
✓ Branch 1 taken 295 times.
✓ Branch 2 taken 10388 times.
✓ Branch 3 taken 2469279 times.
✓ Branch 4 taken 2196 times.
✓ Branch 5 taken 8192 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 2196 times.
|
2479962 | COPYSEQ(sq_inplace_repeat); |
| 6092 | } | ||
| 6093 | |||
| 6094 |
4/4✓ Branch 0 taken 4966453 times.
✓ Branch 1 taken 1416239 times.
✓ Branch 2 taken 2487204 times.
✓ Branch 3 taken 2479249 times.
|
6382692 | if (type->tp_as_mapping != NULL && base->tp_as_mapping != NULL) { |
| 6095 | 2487204 | basebase = base->tp_base; | |
| 6096 |
2/2✓ Branch 0 taken 1385454 times.
✓ Branch 1 taken 1101750 times.
|
2487204 | if (basebase->tp_as_mapping == NULL) |
| 6097 | 1385454 | basebase = NULL; | |
| 6098 |
8/8✓ Branch 0 taken 2260416 times.
✓ Branch 1 taken 226788 times.
✓ Branch 2 taken 415246 times.
✓ Branch 3 taken 1845170 times.
✓ Branch 4 taken 167915 times.
✓ Branch 5 taken 247331 times.
✓ Branch 6 taken 16098 times.
✓ Branch 7 taken 151817 times.
|
2487204 | COPYMAP(mp_length); |
| 6099 |
8/8✓ Branch 0 taken 2032176 times.
✓ Branch 1 taken 455028 times.
✓ Branch 2 taken 356013 times.
✓ Branch 3 taken 1676163 times.
✓ Branch 4 taken 159226 times.
✓ Branch 5 taken 196787 times.
✓ Branch 6 taken 64996 times.
✓ Branch 7 taken 94230 times.
|
2487204 | COPYMAP(mp_subscript); |
| 6100 |
8/8✓ Branch 0 taken 2388517 times.
✓ Branch 1 taken 98687 times.
✓ Branch 2 taken 44659 times.
✓ Branch 3 taken 2343858 times.
✓ Branch 4 taken 20063 times.
✓ Branch 5 taken 24596 times.
✓ Branch 6 taken 15760 times.
✓ Branch 7 taken 4303 times.
|
2487204 | COPYMAP(mp_ass_subscript); |
| 6101 | } | ||
| 6102 | |||
| 6103 |
4/4✓ Branch 0 taken 4915480 times.
✓ Branch 1 taken 1467212 times.
✓ Branch 2 taken 2319099 times.
✓ Branch 3 taken 2596381 times.
|
6382692 | if (type->tp_as_buffer != NULL && base->tp_as_buffer != NULL) { |
| 6104 | 2319099 | basebase = base->tp_base; | |
| 6105 |
2/2✓ Branch 0 taken 1227137 times.
✓ Branch 1 taken 1091962 times.
|
2319099 | if (basebase->tp_as_buffer == NULL) |
| 6106 | 1227137 | basebase = NULL; | |
| 6107 |
7/8✓ Branch 0 taken 2317647 times.
✓ Branch 1 taken 1452 times.
✓ Branch 2 taken 17550 times.
✓ Branch 3 taken 2300097 times.
✓ Branch 4 taken 8684 times.
✓ Branch 5 taken 8866 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 8684 times.
|
2319099 | COPYBUF(bf_getbuffer); |
| 6108 |
2/8✓ Branch 0 taken 2319099 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2319099 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
|
2319099 | COPYBUF(bf_releasebuffer); |
| 6109 | } | ||
| 6110 | |||
| 6111 | 6382692 | basebase = base->tp_base; | |
| 6112 | |||
| 6113 |
7/8✓ Branch 0 taken 62863 times.
✓ Branch 1 taken 6319829 times.
✓ Branch 2 taken 62863 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 28330 times.
✓ Branch 5 taken 34533 times.
✓ Branch 6 taken 28326 times.
✓ Branch 7 taken 4 times.
|
6382692 | COPYSLOT(tp_dealloc); |
| 6114 |
3/4✓ Branch 0 taken 6382692 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2071462 times.
✓ Branch 3 taken 4311230 times.
|
6382692 | if (type->tp_getattr == NULL && type->tp_getattro == NULL) { |
| 6115 | 2071462 | type->tp_getattr = base->tp_getattr; | |
| 6116 | 2071462 | type->tp_getattro = base->tp_getattro; | |
| 6117 | } | ||
| 6118 |
4/4✓ Branch 0 taken 6382690 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 2438606 times.
✓ Branch 3 taken 3944084 times.
|
6382692 | if (type->tp_setattr == NULL && type->tp_setattro == NULL) { |
| 6119 | 2438606 | type->tp_setattr = base->tp_setattr; | |
| 6120 | 2438606 | type->tp_setattro = base->tp_setattro; | |
| 6121 | } | ||
| 6122 |
7/8✓ Branch 0 taken 4363878 times.
✓ Branch 1 taken 2018814 times.
✓ Branch 2 taken 4363878 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3082118 times.
✓ Branch 5 taken 1281760 times.
✓ Branch 6 taken 858670 times.
✓ Branch 7 taken 2223448 times.
|
6382692 | COPYSLOT(tp_repr); |
| 6123 | /* tp_hash see tp_richcompare */ | ||
| 6124 | { | ||
| 6125 | /* Always inherit tp_vectorcall_offset to support PyVectorcall_Call(). | ||
| 6126 | * If Py_TPFLAGS_HAVE_VECTORCALL is not inherited, then vectorcall | ||
| 6127 | * won't be used automatically. */ | ||
| 6128 |
7/8✓ Branch 0 taken 6328320 times.
✓ Branch 1 taken 54372 times.
✓ Branch 2 taken 27003 times.
✓ Branch 3 taken 6301317 times.
✓ Branch 4 taken 27003 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 23142 times.
✓ Branch 7 taken 3861 times.
|
6382692 | COPYSLOT(tp_vectorcall_offset); |
| 6129 | |||
| 6130 | /* Inherit Py_TPFLAGS_HAVE_VECTORCALL for non-heap types | ||
| 6131 | * if tp_call is not overridden */ | ||
| 6132 |
4/4✓ Branch 0 taken 6152408 times.
✓ Branch 1 taken 230284 times.
✓ Branch 2 taken 23368 times.
✓ Branch 3 taken 6129040 times.
|
12535100 | if (!type->tp_call && |
| 6133 |
2/2✓ Branch 1 taken 4861 times.
✓ Branch 2 taken 18507 times.
|
6175776 | _PyType_HasFeature(base, Py_TPFLAGS_HAVE_VECTORCALL) && |
| 6134 | 23368 | _PyType_HasFeature(type, Py_TPFLAGS_IMMUTABLETYPE)) | |
| 6135 | { | ||
| 6136 | 4861 | type->tp_flags |= Py_TPFLAGS_HAVE_VECTORCALL; | |
| 6137 | } | ||
| 6138 |
7/8✓ Branch 0 taken 6152408 times.
✓ Branch 1 taken 230284 times.
✓ Branch 2 taken 136292 times.
✓ Branch 3 taken 6016116 times.
✓ Branch 4 taken 136292 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 94429 times.
✓ Branch 7 taken 41863 times.
|
6382692 | COPYSLOT(tp_call); |
| 6139 | } | ||
| 6140 |
7/8✓ Branch 0 taken 4925614 times.
✓ Branch 1 taken 1457078 times.
✓ Branch 2 taken 4925614 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3069326 times.
✓ Branch 5 taken 1856288 times.
✓ Branch 6 taken 552338 times.
✓ Branch 7 taken 2516988 times.
|
6382692 | COPYSLOT(tp_str); |
| 6141 | { | ||
| 6142 | /* Copy comparison-related slots only when | ||
| 6143 | not overriding them anywhere */ | ||
| 6144 |
2/2✓ Branch 0 taken 2502029 times.
✓ Branch 1 taken 3880663 times.
|
6382692 | if (type->tp_richcompare == NULL && |
| 6145 |
2/2✓ Branch 0 taken 2464791 times.
✓ Branch 1 taken 37238 times.
|
2502029 | type->tp_hash == NULL) |
| 6146 | { | ||
| 6147 | 2464791 | int r = overrides_hash(type); | |
| 6148 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2464791 times.
|
2464791 | if (r < 0) { |
| 6149 | ✗ | return -1; | |
| 6150 | } | ||
| 6151 |
2/2✓ Branch 0 taken 2236451 times.
✓ Branch 1 taken 228340 times.
|
2464791 | if (!r) { |
| 6152 | 2236451 | type->tp_richcompare = base->tp_richcompare; | |
| 6153 | 2236451 | type->tp_hash = base->tp_hash; | |
| 6154 | } | ||
| 6155 | } | ||
| 6156 | } | ||
| 6157 | { | ||
| 6158 |
7/8✓ Branch 0 taken 5368762 times.
✓ Branch 1 taken 1013930 times.
✓ Branch 2 taken 600585 times.
✓ Branch 3 taken 4768177 times.
✓ Branch 4 taken 600585 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 394750 times.
✓ Branch 7 taken 205835 times.
|
6382692 | COPYSLOT(tp_iter); |
| 6159 |
7/8✓ Branch 0 taken 4245951 times.
✓ Branch 1 taken 2136741 times.
✓ Branch 2 taken 1630860 times.
✓ Branch 3 taken 2615091 times.
✓ Branch 4 taken 1630860 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 843227 times.
✓ Branch 7 taken 787633 times.
|
6382692 | COPYSLOT(tp_iternext); |
| 6160 | } | ||
| 6161 | { | ||
| 6162 |
7/8✓ Branch 0 taken 6325086 times.
✓ Branch 1 taken 57606 times.
✓ Branch 2 taken 14101 times.
✓ Branch 3 taken 6310985 times.
✓ Branch 4 taken 14101 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 14079 times.
✓ Branch 7 taken 22 times.
|
6382692 | COPYSLOT(tp_descr_get); |
| 6163 | /* Inherit Py_TPFLAGS_METHOD_DESCRIPTOR if tp_descr_get was inherited, | ||
| 6164 | * but only for extension types */ | ||
| 6165 |
2/2✓ Branch 0 taken 14146 times.
✓ Branch 1 taken 6368546 times.
|
6382692 | if (base->tp_descr_get && |
| 6166 |
4/4✓ Branch 0 taken 14079 times.
✓ Branch 1 taken 67 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 14077 times.
|
28225 | type->tp_descr_get == base->tp_descr_get && |
| 6167 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
14081 | _PyType_HasFeature(type, Py_TPFLAGS_IMMUTABLETYPE) && |
| 6168 | 2 | _PyType_HasFeature(base, Py_TPFLAGS_METHOD_DESCRIPTOR)) | |
| 6169 | { | ||
| 6170 | 2 | type->tp_flags |= Py_TPFLAGS_METHOD_DESCRIPTOR; | |
| 6171 | } | ||
| 6172 |
7/8✓ Branch 0 taken 6362852 times.
✓ Branch 1 taken 19840 times.
✓ Branch 2 taken 6147 times.
✓ Branch 3 taken 6356705 times.
✓ Branch 4 taken 6147 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 6103 times.
✓ Branch 7 taken 44 times.
|
6382692 | COPYSLOT(tp_descr_set); |
| 6173 |
3/8✓ Branch 0 taken 1369313 times.
✓ Branch 1 taken 5013379 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1369313 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
|
6382692 | COPYSLOT(tp_dictoffset); |
| 6174 |
7/8✓ Branch 0 taken 3864339 times.
✓ Branch 1 taken 2518353 times.
✓ Branch 2 taken 3864339 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2437992 times.
✓ Branch 5 taken 1426347 times.
✓ Branch 6 taken 728304 times.
✓ Branch 7 taken 1709688 times.
|
6382692 | COPYSLOT(tp_init); |
| 6175 |
7/8✓ Branch 0 taken 1540158 times.
✓ Branch 1 taken 4842534 times.
✓ Branch 2 taken 1540158 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 742824 times.
✓ Branch 5 taken 797334 times.
✓ Branch 6 taken 242 times.
✓ Branch 7 taken 742582 times.
|
6382692 | COPYSLOT(tp_alloc); |
| 6176 |
7/8✓ Branch 0 taken 6364379 times.
✓ Branch 1 taken 18313 times.
✓ Branch 2 taken 18766 times.
✓ Branch 3 taken 6345613 times.
✓ Branch 4 taken 18766 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 14905 times.
✓ Branch 7 taken 3861 times.
|
6382692 | COPYSLOT(tp_is_gc); |
| 6177 |
7/8✓ Branch 0 taken 6282157 times.
✓ Branch 1 taken 100535 times.
✓ Branch 2 taken 177121 times.
✓ Branch 3 taken 6105036 times.
✓ Branch 4 taken 177121 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 75456 times.
✓ Branch 7 taken 101665 times.
|
6382692 | COPYSLOT(tp_finalize); |
| 6178 | 6382692 | if ((type->tp_flags & Py_TPFLAGS_HAVE_GC) == | |
| 6179 |
2/2✓ Branch 0 taken 3974849 times.
✓ Branch 1 taken 2407843 times.
|
6382692 | (base->tp_flags & Py_TPFLAGS_HAVE_GC)) { |
| 6180 | /* They agree about gc. */ | ||
| 6181 |
7/8✓ Branch 0 taken 858764 times.
✓ Branch 1 taken 3116085 times.
✓ Branch 2 taken 858764 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 748051 times.
✓ Branch 5 taken 110713 times.
✓ Branch 6 taken 342692 times.
✓ Branch 7 taken 405359 times.
|
3974849 | COPYSLOT(tp_free); |
| 6182 | } | ||
| 6183 |
1/2✓ Branch 0 taken 2407843 times.
✗ Branch 1 not taken.
|
2407843 | else if ((type->tp_flags & Py_TPFLAGS_HAVE_GC) && |
| 6184 |
2/2✓ Branch 0 taken 259191 times.
✓ Branch 1 taken 2148652 times.
|
2407843 | type->tp_free == NULL && |
| 6185 |
1/2✓ Branch 0 taken 259191 times.
✗ Branch 1 not taken.
|
259191 | base->tp_free == PyObject_Free) { |
| 6186 | /* A bit of magic to plug in the correct default | ||
| 6187 | * tp_free function when a derived class adds gc, | ||
| 6188 | * didn't define tp_free, and the base uses the | ||
| 6189 | * default non-gc tp_free. | ||
| 6190 | */ | ||
| 6191 | 259191 | type->tp_free = PyObject_GC_Del; | |
| 6192 | } | ||
| 6193 | /* else they didn't agree about gc, and there isn't something | ||
| 6194 | * obvious to be done -- the type is on its own. | ||
| 6195 | */ | ||
| 6196 | } | ||
| 6197 | 6382692 | return 0; | |
| 6198 | } | ||
| 6199 | |||
| 6200 | static int add_operators(PyTypeObject *); | ||
| 6201 | static int add_tp_new_wrapper(PyTypeObject *type); | ||
| 6202 | |||
| 6203 | #define COLLECTION_FLAGS (Py_TPFLAGS_SEQUENCE | Py_TPFLAGS_MAPPING) | ||
| 6204 | |||
| 6205 | static int | ||
| 6206 | 2484676 | type_ready_pre_checks(PyTypeObject *type) | |
| 6207 | { | ||
| 6208 | /* Consistency checks for PEP 590: | ||
| 6209 | * - Py_TPFLAGS_METHOD_DESCRIPTOR requires tp_descr_get | ||
| 6210 | * - Py_TPFLAGS_HAVE_VECTORCALL requires tp_call and | ||
| 6211 | * tp_vectorcall_offset > 0 | ||
| 6212 | * To avoid mistakes, we require this before inheriting. | ||
| 6213 | */ | ||
| 6214 | 2484676 | if (type->tp_flags & Py_TPFLAGS_METHOD_DESCRIPTOR) { | |
| 6215 | _PyObject_ASSERT((PyObject *)type, type->tp_descr_get != NULL); | ||
| 6216 | } | ||
| 6217 | 2484676 | if (type->tp_flags & Py_TPFLAGS_HAVE_VECTORCALL) { | |
| 6218 | _PyObject_ASSERT((PyObject *)type, type->tp_vectorcall_offset > 0); | ||
| 6219 | _PyObject_ASSERT((PyObject *)type, type->tp_call != NULL); | ||
| 6220 | } | ||
| 6221 | |||
| 6222 | /* Consistency checks for pattern matching | ||
| 6223 | * Py_TPFLAGS_SEQUENCE and Py_TPFLAGS_MAPPING are mutually exclusive */ | ||
| 6224 | _PyObject_ASSERT((PyObject *)type, (type->tp_flags & COLLECTION_FLAGS) != COLLECTION_FLAGS); | ||
| 6225 | |||
| 6226 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2484676 times.
|
2484676 | if (type->tp_name == NULL) { |
| 6227 | ✗ | PyErr_Format(PyExc_SystemError, | |
| 6228 | "Type does not define the tp_name field."); | ||
| 6229 | ✗ | return -1; | |
| 6230 | } | ||
| 6231 | 2484676 | return 0; | |
| 6232 | } | ||
| 6233 | |||
| 6234 | |||
| 6235 | static int | ||
| 6236 | 2484676 | type_ready_set_bases(PyTypeObject *type) | |
| 6237 | { | ||
| 6238 | /* Initialize tp_base (defaults to BaseObject unless that's us) */ | ||
| 6239 | 2484676 | PyTypeObject *base = type->tp_base; | |
| 6240 |
4/4✓ Branch 0 taken 448669 times.
✓ Branch 1 taken 2036007 times.
✓ Branch 2 taken 445261 times.
✓ Branch 3 taken 3408 times.
|
2484676 | if (base == NULL && type != &PyBaseObject_Type) { |
| 6241 | 445261 | base = &PyBaseObject_Type; | |
| 6242 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 445261 times.
|
445261 | if (type->tp_flags & Py_TPFLAGS_HEAPTYPE) { |
| 6243 | ✗ | type->tp_base = (PyTypeObject*)Py_NewRef((PyObject*)base); | |
| 6244 | } | ||
| 6245 | else { | ||
| 6246 | 445261 | type->tp_base = base; | |
| 6247 | } | ||
| 6248 | } | ||
| 6249 | assert(type->tp_base != NULL || type == &PyBaseObject_Type); | ||
| 6250 | |||
| 6251 | /* Now the only way base can still be NULL is if type is | ||
| 6252 | * &PyBaseObject_Type. */ | ||
| 6253 | |||
| 6254 | /* Initialize the base class */ | ||
| 6255 |
3/4✓ Branch 0 taken 2481268 times.
✓ Branch 1 taken 3408 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2481268 times.
|
2484676 | if (base != NULL && !_PyType_IsReady(base)) { |
| 6256 | ✗ | if (PyType_Ready(base) < 0) { | |
| 6257 | ✗ | return -1; | |
| 6258 | } | ||
| 6259 | } | ||
| 6260 | |||
| 6261 | /* Initialize ob_type if NULL. This means extensions that want to be | ||
| 6262 | compilable separately on Windows can call PyType_Ready() instead of | ||
| 6263 | initializing the ob_type field of their type objects. */ | ||
| 6264 | /* The test for base != NULL is really unnecessary, since base is only | ||
| 6265 | NULL when type is &PyBaseObject_Type, and we know its ob_type is | ||
| 6266 | not NULL (it's initialized to &PyType_Type). But coverity doesn't | ||
| 6267 | know that. */ | ||
| 6268 |
3/4✓ Branch 1 taken 404553 times.
✓ Branch 2 taken 2080123 times.
✓ Branch 3 taken 404553 times.
✗ Branch 4 not taken.
|
2484676 | if (Py_IS_TYPE(type, NULL) && base != NULL) { |
| 6269 | 404553 | Py_SET_TYPE(type, Py_TYPE(base)); | |
| 6270 | } | ||
| 6271 | |||
| 6272 | /* Initialize tp_bases */ | ||
| 6273 | 2484676 | PyObject *bases = type->tp_bases; | |
| 6274 |
2/2✓ Branch 0 taken 773989 times.
✓ Branch 1 taken 1710687 times.
|
2484676 | if (bases == NULL) { |
| 6275 | 773989 | PyTypeObject *base = type->tp_base; | |
| 6276 |
2/2✓ Branch 0 taken 3408 times.
✓ Branch 1 taken 770581 times.
|
773989 | if (base == NULL) { |
| 6277 | 3408 | bases = PyTuple_New(0); | |
| 6278 | } | ||
| 6279 | else { | ||
| 6280 | 770581 | bases = PyTuple_Pack(1, base); | |
| 6281 | } | ||
| 6282 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 773989 times.
|
773989 | if (bases == NULL) { |
| 6283 | ✗ | return -1; | |
| 6284 | } | ||
| 6285 | 773989 | type->tp_bases = bases; | |
| 6286 | } | ||
| 6287 | 2484676 | return 0; | |
| 6288 | } | ||
| 6289 | |||
| 6290 | |||
| 6291 | static int | ||
| 6292 | 2484676 | type_ready_set_dict(PyTypeObject *type) | |
| 6293 | { | ||
| 6294 |
2/2✓ Branch 0 taken 1582753 times.
✓ Branch 1 taken 901923 times.
|
2484676 | if (type->tp_dict != NULL) { |
| 6295 | 1582753 | return 0; | |
| 6296 | } | ||
| 6297 | |||
| 6298 | 901923 | PyObject *dict = PyDict_New(); | |
| 6299 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 901923 times.
|
901923 | if (dict == NULL) { |
| 6300 | ✗ | return -1; | |
| 6301 | } | ||
| 6302 | 901923 | type->tp_dict = dict; | |
| 6303 | 901923 | return 0; | |
| 6304 | } | ||
| 6305 | |||
| 6306 | |||
| 6307 | /* If the type dictionary doesn't contain a __doc__, set it from | ||
| 6308 | the tp_doc slot. */ | ||
| 6309 | static int | ||
| 6310 | 2484676 | type_dict_set_doc(PyTypeObject *type) | |
| 6311 | { | ||
| 6312 | 2484676 | int r = PyDict_Contains(type->tp_dict, &_Py_ID(__doc__)); | |
| 6313 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2484676 times.
|
2484676 | if (r < 0) { |
| 6314 | ✗ | return -1; | |
| 6315 | } | ||
| 6316 |
2/2✓ Branch 0 taken 1082496 times.
✓ Branch 1 taken 1402180 times.
|
2484676 | if (r > 0) { |
| 6317 | 1082496 | return 0; | |
| 6318 | } | ||
| 6319 | |||
| 6320 |
2/2✓ Branch 0 taken 590042 times.
✓ Branch 1 taken 812138 times.
|
1402180 | if (type->tp_doc != NULL) { |
| 6321 | const char *doc_str; | ||
| 6322 | 590042 | doc_str = _PyType_DocWithoutSignature(type->tp_name, type->tp_doc); | |
| 6323 | 590042 | PyObject *doc = PyUnicode_FromString(doc_str); | |
| 6324 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 590042 times.
|
590042 | if (doc == NULL) { |
| 6325 | ✗ | return -1; | |
| 6326 | } | ||
| 6327 | |||
| 6328 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 590042 times.
|
590042 | if (PyDict_SetItem(type->tp_dict, &_Py_ID(__doc__), doc) < 0) { |
| 6329 | ✗ | Py_DECREF(doc); | |
| 6330 | ✗ | return -1; | |
| 6331 | } | ||
| 6332 | 590042 | Py_DECREF(doc); | |
| 6333 | } | ||
| 6334 | else { | ||
| 6335 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 812138 times.
|
812138 | if (PyDict_SetItem(type->tp_dict, &_Py_ID(__doc__), Py_None) < 0) { |
| 6336 | ✗ | return -1; | |
| 6337 | } | ||
| 6338 | } | ||
| 6339 | 1402180 | return 0; | |
| 6340 | } | ||
| 6341 | |||
| 6342 | |||
| 6343 | static int | ||
| 6344 | 2484676 | type_ready_fill_dict(PyTypeObject *type) | |
| 6345 | { | ||
| 6346 | /* Add type-specific descriptors to tp_dict */ | ||
| 6347 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 2484676 times.
|
2484676 | if (add_operators(type) < 0) { |
| 6348 | ✗ | return -1; | |
| 6349 | } | ||
| 6350 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 2484676 times.
|
2484676 | if (type_add_methods(type) < 0) { |
| 6351 | ✗ | return -1; | |
| 6352 | } | ||
| 6353 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 2484676 times.
|
2484676 | if (type_add_members(type) < 0) { |
| 6354 | ✗ | return -1; | |
| 6355 | } | ||
| 6356 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 2484676 times.
|
2484676 | if (type_add_getset(type) < 0) { |
| 6357 | ✗ | return -1; | |
| 6358 | } | ||
| 6359 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 2484676 times.
|
2484676 | if (type_dict_set_doc(type) < 0) { |
| 6360 | ✗ | return -1; | |
| 6361 | } | ||
| 6362 | 2484676 | return 0; | |
| 6363 | } | ||
| 6364 | |||
| 6365 | |||
| 6366 | static int | ||
| 6367 | 2484676 | type_ready_mro(PyTypeObject *type) | |
| 6368 | { | ||
| 6369 | /* Calculate method resolution order */ | ||
| 6370 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 2484676 times.
|
2484676 | if (mro_internal(type, NULL) < 0) { |
| 6371 | ✗ | return -1; | |
| 6372 | } | ||
| 6373 | assert(type->tp_mro != NULL); | ||
| 6374 | assert(PyTuple_Check(type->tp_mro)); | ||
| 6375 | |||
| 6376 | /* All bases of statically allocated type should be statically allocated */ | ||
| 6377 |
2/2✓ Branch 0 taken 773989 times.
✓ Branch 1 taken 1710687 times.
|
2484676 | if (!(type->tp_flags & Py_TPFLAGS_HEAPTYPE)) { |
| 6378 | 773989 | PyObject *mro = type->tp_mro; | |
| 6379 | 773989 | Py_ssize_t n = PyTuple_GET_SIZE(mro); | |
| 6380 |
2/2✓ Branch 0 taken 2261383 times.
✓ Branch 1 taken 773989 times.
|
3035372 | for (Py_ssize_t i = 0; i < n; i++) { |
| 6381 | 2261383 | PyTypeObject *base = _PyType_CAST(PyTuple_GET_ITEM(mro, i)); | |
| 6382 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2261383 times.
|
2261383 | if (base->tp_flags & Py_TPFLAGS_HEAPTYPE) { |
| 6383 | ✗ | PyErr_Format(PyExc_TypeError, | |
| 6384 | "type '%.100s' is not dynamically allocated but " | ||
| 6385 | "its base type '%.100s' is dynamically allocated", | ||
| 6386 | type->tp_name, base->tp_name); | ||
| 6387 | ✗ | return -1; | |
| 6388 | } | ||
| 6389 | } | ||
| 6390 | } | ||
| 6391 | 2484676 | return 0; | |
| 6392 | } | ||
| 6393 | |||
| 6394 | |||
| 6395 | // For static types, inherit tp_as_xxx structures from the base class | ||
| 6396 | // if it's NULL. | ||
| 6397 | // | ||
| 6398 | // For heap types, tp_as_xxx structures are not NULL: they are set to the | ||
| 6399 | // PyHeapTypeObject.as_xxx fields by type_new_alloc(). | ||
| 6400 | static void | ||
| 6401 | 2481268 | type_ready_inherit_as_structs(PyTypeObject *type, PyTypeObject *base) | |
| 6402 | { | ||
| 6403 |
2/2✓ Branch 0 taken 749034 times.
✓ Branch 1 taken 1732234 times.
|
2481268 | if (type->tp_as_async == NULL) { |
| 6404 | 749034 | type->tp_as_async = base->tp_as_async; | |
| 6405 | } | ||
| 6406 |
2/2✓ Branch 0 taken 681751 times.
✓ Branch 1 taken 1799517 times.
|
2481268 | if (type->tp_as_number == NULL) { |
| 6407 | 681751 | type->tp_as_number = base->tp_as_number; | |
| 6408 | } | ||
| 6409 |
2/2✓ Branch 0 taken 704620 times.
✓ Branch 1 taken 1776648 times.
|
2481268 | if (type->tp_as_sequence == NULL) { |
| 6410 | 704620 | type->tp_as_sequence = base->tp_as_sequence; | |
| 6411 | } | ||
| 6412 |
2/2✓ Branch 0 taken 703318 times.
✓ Branch 1 taken 1777950 times.
|
2481268 | if (type->tp_as_mapping == NULL) { |
| 6413 | 703318 | type->tp_as_mapping = base->tp_as_mapping; | |
| 6414 | } | ||
| 6415 |
2/2✓ Branch 0 taken 751851 times.
✓ Branch 1 taken 1729417 times.
|
2481268 | if (type->tp_as_buffer == NULL) { |
| 6416 | 751851 | type->tp_as_buffer = base->tp_as_buffer; | |
| 6417 | } | ||
| 6418 | 2481268 | } | |
| 6419 | |||
| 6420 | static void | ||
| 6421 | 6382692 | inherit_patma_flags(PyTypeObject *type, PyTypeObject *base) { | |
| 6422 |
2/2✓ Branch 0 taken 5945450 times.
✓ Branch 1 taken 437242 times.
|
6382692 | if ((type->tp_flags & COLLECTION_FLAGS) == 0) { |
| 6423 | 5945450 | type->tp_flags |= base->tp_flags & COLLECTION_FLAGS; | |
| 6424 | } | ||
| 6425 | 6382692 | } | |
| 6426 | |||
| 6427 | static int | ||
| 6428 | 2484676 | type_ready_inherit(PyTypeObject *type) | |
| 6429 | { | ||
| 6430 | /* Inherit special flags from dominant base */ | ||
| 6431 | 2484676 | PyTypeObject *base = type->tp_base; | |
| 6432 |
2/2✓ Branch 0 taken 2481268 times.
✓ Branch 1 taken 3408 times.
|
2484676 | if (base != NULL) { |
| 6433 | 2481268 | inherit_special(type, base); | |
| 6434 | } | ||
| 6435 | |||
| 6436 | // Inherit slots | ||
| 6437 | 2484676 | PyObject *mro = type->tp_mro; | |
| 6438 | 2484676 | Py_ssize_t n = PyTuple_GET_SIZE(type->tp_mro); | |
| 6439 |
2/2✓ Branch 0 taken 6382692 times.
✓ Branch 1 taken 2484676 times.
|
8867368 | for (Py_ssize_t i = 1; i < n; i++) { |
| 6440 | 6382692 | PyObject *b = PyTuple_GET_ITEM(mro, i); | |
| 6441 |
1/2✓ Branch 1 taken 6382692 times.
✗ Branch 2 not taken.
|
6382692 | if (PyType_Check(b)) { |
| 6442 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 6382692 times.
|
6382692 | if (inherit_slots(type, (PyTypeObject *)b) < 0) { |
| 6443 | ✗ | return -1; | |
| 6444 | } | ||
| 6445 | 6382692 | inherit_patma_flags(type, (PyTypeObject *)b); | |
| 6446 | } | ||
| 6447 | } | ||
| 6448 | |||
| 6449 |
2/2✓ Branch 0 taken 2481268 times.
✓ Branch 1 taken 3408 times.
|
2484676 | if (base != NULL) { |
| 6450 | 2481268 | type_ready_inherit_as_structs(type, base); | |
| 6451 | } | ||
| 6452 | |||
| 6453 | /* Sanity check for tp_free. */ | ||
| 6454 |
4/4✓ Branch 1 taken 2334139 times.
✓ Branch 2 taken 150537 times.
✓ Branch 3 taken 1985980 times.
✓ Branch 4 taken 348159 times.
|
2484676 | if (_PyType_IS_GC(type) && (type->tp_flags & Py_TPFLAGS_BASETYPE) && |
| 6455 |
2/4✓ Branch 0 taken 1985980 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1985980 times.
|
1985980 | (type->tp_free == NULL || type->tp_free == PyObject_Del)) |
| 6456 | { | ||
| 6457 | /* This base class needs to call tp_free, but doesn't have | ||
| 6458 | * one, or its tp_free is for non-gc'ed objects. | ||
| 6459 | */ | ||
| 6460 | ✗ | PyErr_Format(PyExc_TypeError, "type '%.100s' participates in " | |
| 6461 | "gc and is a base type but has inappropriate " | ||
| 6462 | "tp_free slot", | ||
| 6463 | type->tp_name); | ||
| 6464 | ✗ | return -1; | |
| 6465 | } | ||
| 6466 | |||
| 6467 | 2484676 | return 0; | |
| 6468 | } | ||
| 6469 | |||
| 6470 | |||
| 6471 | /* Hack for tp_hash and __hash__. | ||
| 6472 | If after all that, tp_hash is still NULL, and __hash__ is not in | ||
| 6473 | tp_dict, set tp_hash to PyObject_HashNotImplemented and | ||
| 6474 | tp_dict['__hash__'] equal to None. | ||
| 6475 | This signals that __hash__ is not inherited. */ | ||
| 6476 | static int | ||
| 6477 | 2484676 | type_ready_set_hash(PyTypeObject *type) | |
| 6478 | { | ||
| 6479 |
2/2✓ Branch 0 taken 2354763 times.
✓ Branch 1 taken 129913 times.
|
2484676 | if (type->tp_hash != NULL) { |
| 6480 | 2354763 | return 0; | |
| 6481 | } | ||
| 6482 | |||
| 6483 | 129913 | int r = PyDict_Contains(type->tp_dict, &_Py_ID(__hash__)); | |
| 6484 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 129913 times.
|
129913 | if (r < 0) { |
| 6485 | ✗ | return -1; | |
| 6486 | } | ||
| 6487 |
2/2✓ Branch 0 taken 54811 times.
✓ Branch 1 taken 75102 times.
|
129913 | if (r > 0) { |
| 6488 | 54811 | return 0; | |
| 6489 | } | ||
| 6490 | |||
| 6491 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 75102 times.
|
75102 | if (PyDict_SetItem(type->tp_dict, &_Py_ID(__hash__), Py_None) < 0) { |
| 6492 | ✗ | return -1; | |
| 6493 | } | ||
| 6494 | 75102 | type->tp_hash = PyObject_HashNotImplemented; | |
| 6495 | 75102 | return 0; | |
| 6496 | } | ||
| 6497 | |||
| 6498 | |||
| 6499 | /* Link into each base class's list of subclasses */ | ||
| 6500 | static int | ||
| 6501 | 2484676 | type_ready_add_subclasses(PyTypeObject *type) | |
| 6502 | { | ||
| 6503 | 2484676 | PyObject *bases = type->tp_bases; | |
| 6504 | 2484676 | Py_ssize_t nbase = PyTuple_GET_SIZE(bases); | |
| 6505 |
2/2✓ Branch 0 taken 2635075 times.
✓ Branch 1 taken 2484676 times.
|
5119751 | for (Py_ssize_t i = 0; i < nbase; i++) { |
| 6506 | 2635075 | PyObject *b = PyTuple_GET_ITEM(bases, i); | |
| 6507 |
2/4✓ Branch 1 taken 2635075 times.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2635075 times.
|
2635075 | if (PyType_Check(b) && add_subclass((PyTypeObject *)b, type) < 0) { |
| 6508 | ✗ | return -1; | |
| 6509 | } | ||
| 6510 | } | ||
| 6511 | 2484676 | return 0; | |
| 6512 | } | ||
| 6513 | |||
| 6514 | |||
| 6515 | // Set tp_new and the "__new__" key in the type dictionary. | ||
| 6516 | // Use the Py_TPFLAGS_DISALLOW_INSTANTIATION flag. | ||
| 6517 | static int | ||
| 6518 | 2484676 | type_ready_set_new(PyTypeObject *type) | |
| 6519 | { | ||
| 6520 | 2484676 | PyTypeObject *base = type->tp_base; | |
| 6521 | /* The condition below could use some explanation. | ||
| 6522 | |||
| 6523 | It appears that tp_new is not inherited for static types whose base | ||
| 6524 | class is 'object'; this seems to be a precaution so that old extension | ||
| 6525 | types don't suddenly become callable (object.__new__ wouldn't insure the | ||
| 6526 | invariants that the extension type's own factory function ensures). | ||
| 6527 | |||
| 6528 | Heap types, of course, are under our control, so they do inherit tp_new; | ||
| 6529 | static extension types that specify some other built-in type as the | ||
| 6530 | default also inherit object.__new__. */ | ||
| 6531 |
2/2✓ Branch 0 taken 1957693 times.
✓ Branch 1 taken 526983 times.
|
2484676 | if (type->tp_new == NULL |
| 6532 |
2/2✓ Branch 0 taken 719501 times.
✓ Branch 1 taken 1238192 times.
|
1957693 | && base == &PyBaseObject_Type |
| 6533 |
2/2✓ Branch 0 taken 213709 times.
✓ Branch 1 taken 505792 times.
|
719501 | && !(type->tp_flags & Py_TPFLAGS_HEAPTYPE)) |
| 6534 | { | ||
| 6535 | 213709 | type->tp_flags |= Py_TPFLAGS_DISALLOW_INSTANTIATION; | |
| 6536 | } | ||
| 6537 | |||
| 6538 |
2/2✓ Branch 0 taken 2223487 times.
✓ Branch 1 taken 261189 times.
|
2484676 | if (!(type->tp_flags & Py_TPFLAGS_DISALLOW_INSTANTIATION)) { |
| 6539 |
2/2✓ Branch 0 taken 520144 times.
✓ Branch 1 taken 1703343 times.
|
2223487 | if (type->tp_new != NULL) { |
| 6540 | // If "__new__" key does not exists in the type dictionary, | ||
| 6541 | // set it to tp_new_wrapper(). | ||
| 6542 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 520144 times.
|
520144 | if (add_tp_new_wrapper(type) < 0) { |
| 6543 | ✗ | return -1; | |
| 6544 | } | ||
| 6545 | } | ||
| 6546 | else { | ||
| 6547 | // tp_new is NULL: inherit tp_new from base | ||
| 6548 | 1703343 | type->tp_new = base->tp_new; | |
| 6549 | } | ||
| 6550 | } | ||
| 6551 | else { | ||
| 6552 | // Py_TPFLAGS_DISALLOW_INSTANTIATION sets tp_new to NULL | ||
| 6553 | 261189 | type->tp_new = NULL; | |
| 6554 | } | ||
| 6555 | 2484676 | return 0; | |
| 6556 | } | ||
| 6557 | |||
| 6558 | |||
| 6559 | static int | ||
| 6560 | 2484676 | type_ready_post_checks(PyTypeObject *type) | |
| 6561 | { | ||
| 6562 | // bpo-44263: tp_traverse is required if Py_TPFLAGS_HAVE_GC is set. | ||
| 6563 | // Note: tp_clear is optional. | ||
| 6564 |
2/2✓ Branch 0 taken 2334139 times.
✓ Branch 1 taken 150537 times.
|
2484676 | if (type->tp_flags & Py_TPFLAGS_HAVE_GC |
| 6565 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2334139 times.
|
2334139 | && type->tp_traverse == NULL) |
| 6566 | { | ||
| 6567 | ✗ | PyErr_Format(PyExc_SystemError, | |
| 6568 | "type %s has the Py_TPFLAGS_HAVE_GC flag " | ||
| 6569 | "but has no traverse function", | ||
| 6570 | type->tp_name); | ||
| 6571 | ✗ | return -1; | |
| 6572 | } | ||
| 6573 | 2484676 | return 0; | |
| 6574 | } | ||
| 6575 | |||
| 6576 | |||
| 6577 | static int | ||
| 6578 | 2484676 | type_ready(PyTypeObject *type) | |
| 6579 | { | ||
| 6580 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 2484676 times.
|
2484676 | if (type_ready_pre_checks(type) < 0) { |
| 6581 | ✗ | return -1; | |
| 6582 | } | ||
| 6583 | |||
| 6584 | #ifdef Py_TRACE_REFS | ||
| 6585 | /* PyType_Ready is the closest thing we have to a choke point | ||
| 6586 | * for type objects, so is the best place I can think of to try | ||
| 6587 | * to get type objects into the doubly-linked list of all objects. | ||
| 6588 | * Still, not all type objects go through PyType_Ready. | ||
| 6589 | */ | ||
| 6590 | _Py_AddToAllObjects((PyObject *)type, 0); | ||
| 6591 | #endif | ||
| 6592 | |||
| 6593 | /* Initialize tp_dict: _PyType_IsReady() tests if tp_dict != NULL */ | ||
| 6594 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 2484676 times.
|
2484676 | if (type_ready_set_dict(type) < 0) { |
| 6595 | ✗ | return -1; | |
| 6596 | } | ||
| 6597 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 2484676 times.
|
2484676 | if (type_ready_set_bases(type) < 0) { |
| 6598 | ✗ | return -1; | |
| 6599 | } | ||
| 6600 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 2484676 times.
|
2484676 | if (type_ready_mro(type) < 0) { |
| 6601 | ✗ | return -1; | |
| 6602 | } | ||
| 6603 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 2484676 times.
|
2484676 | if (type_ready_set_new(type) < 0) { |
| 6604 | ✗ | return -1; | |
| 6605 | } | ||
| 6606 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 2484676 times.
|
2484676 | if (type_ready_fill_dict(type) < 0) { |
| 6607 | ✗ | return -1; | |
| 6608 | } | ||
| 6609 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 2484676 times.
|
2484676 | if (type_ready_inherit(type) < 0) { |
| 6610 | ✗ | return -1; | |
| 6611 | } | ||
| 6612 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 2484676 times.
|
2484676 | if (type_ready_set_hash(type) < 0) { |
| 6613 | ✗ | return -1; | |
| 6614 | } | ||
| 6615 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 2484676 times.
|
2484676 | if (type_ready_add_subclasses(type) < 0) { |
| 6616 | ✗ | return -1; | |
| 6617 | } | ||
| 6618 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 2484676 times.
|
2484676 | if (type_ready_post_checks(type) < 0) { |
| 6619 | ✗ | return -1; | |
| 6620 | } | ||
| 6621 | 2484676 | return 0; | |
| 6622 | } | ||
| 6623 | |||
| 6624 | |||
| 6625 | int | ||
| 6626 | 2570118 | PyType_Ready(PyTypeObject *type) | |
| 6627 | { | ||
| 6628 |
2/2✓ Branch 0 taken 85442 times.
✓ Branch 1 taken 2484676 times.
|
2570118 | if (type->tp_flags & Py_TPFLAGS_READY) { |
| 6629 | assert(_PyType_CheckConsistency(type)); | ||
| 6630 | 85442 | return 0; | |
| 6631 | } | ||
| 6632 | _PyObject_ASSERT((PyObject *)type, | ||
| 6633 | (type->tp_flags & Py_TPFLAGS_READYING) == 0); | ||
| 6634 | |||
| 6635 | 2484676 | type->tp_flags |= Py_TPFLAGS_READYING; | |
| 6636 | |||
| 6637 | /* Historically, all static types were immutable. See bpo-43908 */ | ||
| 6638 |
2/2✓ Branch 0 taken 773989 times.
✓ Branch 1 taken 1710687 times.
|
2484676 | if (!(type->tp_flags & Py_TPFLAGS_HEAPTYPE)) { |
| 6639 | 773989 | type->tp_flags |= Py_TPFLAGS_IMMUTABLETYPE; | |
| 6640 | } | ||
| 6641 | |||
| 6642 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 2484676 times.
|
2484676 | if (type_ready(type) < 0) { |
| 6643 | ✗ | type->tp_flags &= ~Py_TPFLAGS_READYING; | |
| 6644 | ✗ | return -1; | |
| 6645 | } | ||
| 6646 | |||
| 6647 | /* All done -- set the ready flag */ | ||
| 6648 | 2484676 | type->tp_flags = (type->tp_flags & ~Py_TPFLAGS_READYING) | Py_TPFLAGS_READY; | |
| 6649 | assert(_PyType_CheckConsistency(type)); | ||
| 6650 | 2484676 | return 0; | |
| 6651 | } | ||
| 6652 | |||
| 6653 | |||
| 6654 | static int | ||
| 6655 | 2639730 | add_subclass(PyTypeObject *base, PyTypeObject *type) | |
| 6656 | { | ||
| 6657 | 2639730 | PyObject *key = PyLong_FromVoidPtr((void *) type); | |
| 6658 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2639730 times.
|
2639730 | if (key == NULL) |
| 6659 | ✗ | return -1; | |
| 6660 | |||
| 6661 | 2639730 | PyObject *ref = PyWeakref_NewRef((PyObject *)type, NULL); | |
| 6662 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2639730 times.
|
2639730 | if (ref == NULL) { |
| 6663 | ✗ | Py_DECREF(key); | |
| 6664 | ✗ | return -1; | |
| 6665 | } | ||
| 6666 | |||
| 6667 | // Only get tp_subclasses after creating the key and value. | ||
| 6668 | // PyWeakref_NewRef() can trigger a garbage collection which can execute | ||
| 6669 | // arbitrary Python code and so modify base->tp_subclasses. | ||
| 6670 | 2639730 | PyObject *subclasses = base->tp_subclasses; | |
| 6671 |
2/2✓ Branch 0 taken 495985 times.
✓ Branch 1 taken 2143745 times.
|
2639730 | if (subclasses == NULL) { |
| 6672 | 495985 | base->tp_subclasses = subclasses = PyDict_New(); | |
| 6673 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 495985 times.
|
495985 | if (subclasses == NULL) { |
| 6674 | ✗ | Py_DECREF(key); | |
| 6675 | ✗ | Py_DECREF(ref); | |
| 6676 | ✗ | return -1; | |
| 6677 | } | ||
| 6678 | } | ||
| 6679 | assert(PyDict_CheckExact(subclasses)); | ||
| 6680 | |||
| 6681 | 2639730 | int result = PyDict_SetItem(subclasses, key, ref); | |
| 6682 | 2639730 | Py_DECREF(ref); | |
| 6683 | 2639730 | Py_DECREF(key); | |
| 6684 | 2639730 | return result; | |
| 6685 | } | ||
| 6686 | |||
| 6687 | static int | ||
| 6688 | 4655 | add_all_subclasses(PyTypeObject *type, PyObject *bases) | |
| 6689 | { | ||
| 6690 | 4655 | Py_ssize_t n = PyTuple_GET_SIZE(bases); | |
| 6691 | 4655 | int res = 0; | |
| 6692 |
2/2✓ Branch 0 taken 4655 times.
✓ Branch 1 taken 4655 times.
|
9310 | for (Py_ssize_t i = 0; i < n; i++) { |
| 6693 | 4655 | PyObject *obj = PyTuple_GET_ITEM(bases, i); | |
| 6694 | // bases tuple must only contain types | ||
| 6695 | 4655 | PyTypeObject *base = _PyType_CAST(obj); | |
| 6696 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 4655 times.
|
4655 | if (add_subclass(base, type) < 0) { |
| 6697 | ✗ | res = -1; | |
| 6698 | } | ||
| 6699 | } | ||
| 6700 | 4655 | return res; | |
| 6701 | } | ||
| 6702 | |||
| 6703 | static void | ||
| 6704 | 2380879 | remove_subclass(PyTypeObject *base, PyTypeObject *type) | |
| 6705 | { | ||
| 6706 | 2380879 | PyObject *subclasses = base->tp_subclasses; // borrowed ref | |
| 6707 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2380879 times.
|
2380879 | if (subclasses == NULL) { |
| 6708 | ✗ | return; | |
| 6709 | } | ||
| 6710 | assert(PyDict_CheckExact(subclasses)); | ||
| 6711 | |||
| 6712 | 2380879 | PyObject *key = PyLong_FromVoidPtr((void *) type); | |
| 6713 |
2/4✓ Branch 0 taken 2380879 times.
✗ Branch 1 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 2380879 times.
|
2380879 | if (key == NULL || PyDict_DelItem(subclasses, key)) { |
| 6714 | /* This can happen if the type initialization errored out before | ||
| 6715 | the base subclasses were updated (e.g. a non-str __qualname__ | ||
| 6716 | was passed in the type dict). */ | ||
| 6717 | ✗ | PyErr_Clear(); | |
| 6718 | } | ||
| 6719 | 2380879 | Py_XDECREF(key); | |
| 6720 | |||
| 6721 |
2/2✓ Branch 1 taken 421958 times.
✓ Branch 2 taken 1958921 times.
|
2380879 | if (PyDict_Size(subclasses) == 0) { |
| 6722 | // Delete the dictionary to save memory. _PyStaticType_Dealloc() | ||
| 6723 | // callers also test if tp_subclasses is NULL to check if a static type | ||
| 6724 | // has no subclass. | ||
| 6725 |
1/2✓ Branch 0 taken 421958 times.
✗ Branch 1 not taken.
|
421958 | Py_CLEAR(base->tp_subclasses); |
| 6726 | } | ||
| 6727 | } | ||
| 6728 | |||
| 6729 | static void | ||
| 6730 | 2251653 | remove_all_subclasses(PyTypeObject *type, PyObject *bases) | |
| 6731 | { | ||
| 6732 | assert(bases != NULL); | ||
| 6733 | // remove_subclass() can clear the current exception | ||
| 6734 | assert(!PyErr_Occurred()); | ||
| 6735 | |||
| 6736 |
2/2✓ Branch 1 taken 2380879 times.
✓ Branch 2 taken 2251653 times.
|
4632532 | for (Py_ssize_t i = 0; i < PyTuple_GET_SIZE(bases); i++) { |
| 6737 | 2380879 | PyObject *base = PyTuple_GET_ITEM(bases, i); | |
| 6738 |
1/2✓ Branch 1 taken 2380879 times.
✗ Branch 2 not taken.
|
2380879 | if (PyType_Check(base)) { |
| 6739 | 2380879 | remove_subclass((PyTypeObject*) base, type); | |
| 6740 | } | ||
| 6741 | } | ||
| 6742 | assert(!PyErr_Occurred()); | ||
| 6743 | 2251653 | } | |
| 6744 | |||
| 6745 | static int | ||
| 6746 | 61177479 | check_num_args(PyObject *ob, int n) | |
| 6747 | { | ||
| 6748 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 61177479 times.
|
61177479 | if (!PyTuple_CheckExact(ob)) { |
| 6749 | ✗ | PyErr_SetString(PyExc_SystemError, | |
| 6750 | "PyArg_UnpackTuple() argument list is not a tuple"); | ||
| 6751 | ✗ | return 0; | |
| 6752 | } | ||
| 6753 |
1/2✓ Branch 1 taken 61177479 times.
✗ Branch 2 not taken.
|
61177479 | if (n == PyTuple_GET_SIZE(ob)) |
| 6754 | 61177479 | return 1; | |
| 6755 | ✗ | PyErr_Format( | |
| 6756 | PyExc_TypeError, | ||
| 6757 | "expected %d argument%s, got %zd", n, n == 1 ? "" : "s", PyTuple_GET_SIZE(ob)); | ||
| 6758 | ✗ | return 0; | |
| 6759 | } | ||
| 6760 | |||
| 6761 | /* Generic wrappers for overloadable 'operators' such as __getitem__ */ | ||
| 6762 | |||
| 6763 | /* There's a wrapper *function* for each distinct function typedef used | ||
| 6764 | for type object slots (e.g. binaryfunc, ternaryfunc, etc.). There's a | ||
| 6765 | wrapper *table* for each distinct operation (e.g. __len__, __add__). | ||
| 6766 | Most tables have only one entry; the tables for binary operators have two | ||
| 6767 | entries, one regular and one with reversed arguments. */ | ||
| 6768 | |||
| 6769 | static PyObject * | ||
| 6770 | 1064 | wrap_lenfunc(PyObject *self, PyObject *args, void *wrapped) | |
| 6771 | { | ||
| 6772 | 1064 | lenfunc func = (lenfunc)wrapped; | |
| 6773 | Py_ssize_t res; | ||
| 6774 | |||
| 6775 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 1064 times.
|
1064 | if (!check_num_args(args, 0)) |
| 6776 | ✗ | return NULL; | |
| 6777 | 1064 | res = (*func)(self); | |
| 6778 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 1064 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
|
1064 | if (res == -1 && PyErr_Occurred()) |
| 6779 | ✗ | return NULL; | |
| 6780 | 1064 | return PyLong_FromSsize_t(res); | |
| 6781 | } | ||
| 6782 | |||
| 6783 | static PyObject * | ||
| 6784 | ✗ | wrap_inquirypred(PyObject *self, PyObject *args, void *wrapped) | |
| 6785 | { | ||
| 6786 | ✗ | inquiry func = (inquiry)wrapped; | |
| 6787 | int res; | ||
| 6788 | |||
| 6789 | ✗ | if (!check_num_args(args, 0)) | |
| 6790 | ✗ | return NULL; | |
| 6791 | ✗ | res = (*func)(self); | |
| 6792 | ✗ | if (res == -1 && PyErr_Occurred()) | |
| 6793 | ✗ | return NULL; | |
| 6794 | ✗ | return PyBool_FromLong((long)res); | |
| 6795 | } | ||
| 6796 | |||
| 6797 | static PyObject * | ||
| 6798 | 4142539 | wrap_binaryfunc(PyObject *self, PyObject *args, void *wrapped) | |
| 6799 | { | ||
| 6800 | 4142539 | binaryfunc func = (binaryfunc)wrapped; | |
| 6801 | PyObject *other; | ||
| 6802 | |||
| 6803 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 4142539 times.
|
4142539 | if (!check_num_args(args, 1)) |
| 6804 | ✗ | return NULL; | |
| 6805 | 4142539 | other = PyTuple_GET_ITEM(args, 0); | |
| 6806 | 4142539 | return (*func)(self, other); | |
| 6807 | } | ||
| 6808 | |||
| 6809 | static PyObject * | ||
| 6810 | ✗ | wrap_binaryfunc_l(PyObject *self, PyObject *args, void *wrapped) | |
| 6811 | { | ||
| 6812 | ✗ | binaryfunc func = (binaryfunc)wrapped; | |
| 6813 | PyObject *other; | ||
| 6814 | |||
| 6815 | ✗ | if (!check_num_args(args, 1)) | |
| 6816 | ✗ | return NULL; | |
| 6817 | ✗ | other = PyTuple_GET_ITEM(args, 0); | |
| 6818 | ✗ | return (*func)(self, other); | |
| 6819 | } | ||
| 6820 | |||
| 6821 | static PyObject * | ||
| 6822 | ✗ | wrap_binaryfunc_r(PyObject *self, PyObject *args, void *wrapped) | |
| 6823 | { | ||
| 6824 | ✗ | binaryfunc func = (binaryfunc)wrapped; | |
| 6825 | PyObject *other; | ||
| 6826 | |||
| 6827 | ✗ | if (!check_num_args(args, 1)) | |
| 6828 | ✗ | return NULL; | |
| 6829 | ✗ | other = PyTuple_GET_ITEM(args, 0); | |
| 6830 | ✗ | return (*func)(other, self); | |
| 6831 | } | ||
| 6832 | |||
| 6833 | static PyObject * | ||
| 6834 | ✗ | wrap_ternaryfunc(PyObject *self, PyObject *args, void *wrapped) | |
| 6835 | { | ||
| 6836 | ✗ | ternaryfunc func = (ternaryfunc)wrapped; | |
| 6837 | PyObject *other; | ||
| 6838 | ✗ | PyObject *third = Py_None; | |
| 6839 | |||
| 6840 | /* Note: This wrapper only works for __pow__() */ | ||
| 6841 | |||
| 6842 | ✗ | if (!PyArg_UnpackTuple(args, "", 1, 2, &other, &third)) | |
| 6843 | ✗ | return NULL; | |
| 6844 | ✗ | return (*func)(self, other, third); | |
| 6845 | } | ||
| 6846 | |||
| 6847 | static PyObject * | ||
| 6848 | ✗ | wrap_ternaryfunc_r(PyObject *self, PyObject *args, void *wrapped) | |
| 6849 | { | ||
| 6850 | ✗ | ternaryfunc func = (ternaryfunc)wrapped; | |
| 6851 | PyObject *other; | ||
| 6852 | ✗ | PyObject *third = Py_None; | |
| 6853 | |||
| 6854 | /* Note: This wrapper only works for __pow__() */ | ||
| 6855 | |||
| 6856 | ✗ | if (!PyArg_UnpackTuple(args, "", 1, 2, &other, &third)) | |
| 6857 | ✗ | return NULL; | |
| 6858 | ✗ | return (*func)(other, self, third); | |
| 6859 | } | ||
| 6860 | |||
| 6861 | static PyObject * | ||
| 6862 | 102520 | wrap_unaryfunc(PyObject *self, PyObject *args, void *wrapped) | |
| 6863 | { | ||
| 6864 | 102520 | unaryfunc func = (unaryfunc)wrapped; | |
| 6865 | |||
| 6866 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 102520 times.
|
102520 | if (!check_num_args(args, 0)) |
| 6867 | ✗ | return NULL; | |
| 6868 | 102520 | return (*func)(self); | |
| 6869 | } | ||
| 6870 | |||
| 6871 | static PyObject * | ||
| 6872 | ✗ | wrap_indexargfunc(PyObject *self, PyObject *args, void *wrapped) | |
| 6873 | { | ||
| 6874 | ✗ | ssizeargfunc func = (ssizeargfunc)wrapped; | |
| 6875 | PyObject* o; | ||
| 6876 | Py_ssize_t i; | ||
| 6877 | |||
| 6878 | ✗ | if (!PyArg_UnpackTuple(args, "", 1, 1, &o)) | |
| 6879 | ✗ | return NULL; | |
| 6880 | ✗ | i = PyNumber_AsSsize_t(o, PyExc_OverflowError); | |
| 6881 | ✗ | if (i == -1 && PyErr_Occurred()) | |
| 6882 | ✗ | return NULL; | |
| 6883 | ✗ | return (*func)(self, i); | |
| 6884 | } | ||
| 6885 | |||
| 6886 | static Py_ssize_t | ||
| 6887 | ✗ | getindex(PyObject *self, PyObject *arg) | |
| 6888 | { | ||
| 6889 | Py_ssize_t i; | ||
| 6890 | |||
| 6891 | ✗ | i = PyNumber_AsSsize_t(arg, PyExc_OverflowError); | |
| 6892 | ✗ | if (i == -1 && PyErr_Occurred()) | |
| 6893 | ✗ | return -1; | |
| 6894 | ✗ | if (i < 0) { | |
| 6895 | ✗ | PySequenceMethods *sq = Py_TYPE(self)->tp_as_sequence; | |
| 6896 | ✗ | if (sq && sq->sq_length) { | |
| 6897 | ✗ | Py_ssize_t n = (*sq->sq_length)(self); | |
| 6898 | ✗ | if (n < 0) { | |
| 6899 | assert(PyErr_Occurred()); | ||
| 6900 | ✗ | return -1; | |
| 6901 | } | ||
| 6902 | ✗ | i += n; | |
| 6903 | } | ||
| 6904 | } | ||
| 6905 | ✗ | return i; | |
| 6906 | } | ||
| 6907 | |||
| 6908 | static PyObject * | ||
| 6909 | ✗ | wrap_sq_item(PyObject *self, PyObject *args, void *wrapped) | |
| 6910 | { | ||
| 6911 | ✗ | ssizeargfunc func = (ssizeargfunc)wrapped; | |
| 6912 | PyObject *arg; | ||
| 6913 | Py_ssize_t i; | ||
| 6914 | |||
| 6915 | ✗ | if (PyTuple_GET_SIZE(args) == 1) { | |
| 6916 | ✗ | arg = PyTuple_GET_ITEM(args, 0); | |
| 6917 | ✗ | i = getindex(self, arg); | |
| 6918 | ✗ | if (i == -1 && PyErr_Occurred()) | |
| 6919 | ✗ | return NULL; | |
| 6920 | ✗ | return (*func)(self, i); | |
| 6921 | } | ||
| 6922 | ✗ | check_num_args(args, 1); | |
| 6923 | assert(PyErr_Occurred()); | ||
| 6924 | ✗ | return NULL; | |
| 6925 | } | ||
| 6926 | |||
| 6927 | static PyObject * | ||
| 6928 | ✗ | wrap_sq_setitem(PyObject *self, PyObject *args, void *wrapped) | |
| 6929 | { | ||
| 6930 | ✗ | ssizeobjargproc func = (ssizeobjargproc)wrapped; | |
| 6931 | Py_ssize_t i; | ||
| 6932 | int res; | ||
| 6933 | PyObject *arg, *value; | ||
| 6934 | |||
| 6935 | ✗ | if (!PyArg_UnpackTuple(args, "", 2, 2, &arg, &value)) | |
| 6936 | ✗ | return NULL; | |
| 6937 | ✗ | i = getindex(self, arg); | |
| 6938 | ✗ | if (i == -1 && PyErr_Occurred()) | |
| 6939 | ✗ | return NULL; | |
| 6940 | ✗ | res = (*func)(self, i, value); | |
| 6941 | ✗ | if (res == -1 && PyErr_Occurred()) | |
| 6942 | ✗ | return NULL; | |
| 6943 | ✗ | Py_RETURN_NONE; | |
| 6944 | } | ||
| 6945 | |||
| 6946 | static PyObject * | ||
| 6947 | ✗ | wrap_sq_delitem(PyObject *self, PyObject *args, void *wrapped) | |
| 6948 | { | ||
| 6949 | ✗ | ssizeobjargproc func = (ssizeobjargproc)wrapped; | |
| 6950 | Py_ssize_t i; | ||
| 6951 | int res; | ||
| 6952 | PyObject *arg; | ||
| 6953 | |||
| 6954 | ✗ | if (!check_num_args(args, 1)) | |
| 6955 | ✗ | return NULL; | |
| 6956 | ✗ | arg = PyTuple_GET_ITEM(args, 0); | |
| 6957 | ✗ | i = getindex(self, arg); | |
| 6958 | ✗ | if (i == -1 && PyErr_Occurred()) | |
| 6959 | ✗ | return NULL; | |
| 6960 | ✗ | res = (*func)(self, i, NULL); | |
| 6961 | ✗ | if (res == -1 && PyErr_Occurred()) | |
| 6962 | ✗ | return NULL; | |
| 6963 | ✗ | Py_RETURN_NONE; | |
| 6964 | } | ||
| 6965 | |||
| 6966 | /* XXX objobjproc is a misnomer; should be objargpred */ | ||
| 6967 | static PyObject * | ||
| 6968 | ✗ | wrap_objobjproc(PyObject *self, PyObject *args, void *wrapped) | |
| 6969 | { | ||
| 6970 | ✗ | objobjproc func = (objobjproc)wrapped; | |
| 6971 | int res; | ||
| 6972 | PyObject *value; | ||
| 6973 | |||
| 6974 | ✗ | if (!check_num_args(args, 1)) | |
| 6975 | ✗ | return NULL; | |
| 6976 | ✗ | value = PyTuple_GET_ITEM(args, 0); | |
| 6977 | ✗ | res = (*func)(self, value); | |
| 6978 | ✗ | if (res == -1 && PyErr_Occurred()) | |
| 6979 | ✗ | return NULL; | |
| 6980 | else | ||
| 6981 | ✗ | return PyBool_FromLong(res); | |
| 6982 | } | ||
| 6983 | |||
| 6984 | static PyObject * | ||
| 6985 | 332567 | wrap_objobjargproc(PyObject *self, PyObject *args, void *wrapped) | |
| 6986 | { | ||
| 6987 | 332567 | objobjargproc func = (objobjargproc)wrapped; | |
| 6988 | int res; | ||
| 6989 | PyObject *key, *value; | ||
| 6990 | |||
| 6991 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 332567 times.
|
332567 | if (!PyArg_UnpackTuple(args, "", 2, 2, &key, &value)) |
| 6992 | ✗ | return NULL; | |
| 6993 | 332567 | res = (*func)(self, key, value); | |
| 6994 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 332567 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
|
332567 | if (res == -1 && PyErr_Occurred()) |
| 6995 | ✗ | return NULL; | |
| 6996 | 332567 | Py_RETURN_NONE; | |
| 6997 | } | ||
| 6998 | |||
| 6999 | static PyObject * | ||
| 7000 | ✗ | wrap_delitem(PyObject *self, PyObject *args, void *wrapped) | |
| 7001 | { | ||
| 7002 | ✗ | objobjargproc func = (objobjargproc)wrapped; | |
| 7003 | int res; | ||
| 7004 | PyObject *key; | ||
| 7005 | |||
| 7006 | ✗ | if (!check_num_args(args, 1)) | |
| 7007 | ✗ | return NULL; | |
| 7008 | ✗ | key = PyTuple_GET_ITEM(args, 0); | |
| 7009 | ✗ | res = (*func)(self, key, NULL); | |
| 7010 | ✗ | if (res == -1 && PyErr_Occurred()) | |
| 7011 | ✗ | return NULL; | |
| 7012 | ✗ | Py_RETURN_NONE; | |
| 7013 | } | ||
| 7014 | |||
| 7015 | /* Helper to check for object.__setattr__ or __delattr__ applied to a type. | ||
| 7016 | This is called the Carlo Verre hack after its discoverer. See | ||
| 7017 | https://mail.python.org/pipermail/python-dev/2003-April/034535.html | ||
| 7018 | */ | ||
| 7019 | static int | ||
| 7020 | 2342099 | hackcheck(PyObject *self, setattrofunc func, const char *what) | |
| 7021 | { | ||
| 7022 | 2342099 | PyTypeObject *type = Py_TYPE(self); | |
| 7023 | 2342099 | PyObject *mro = type->tp_mro; | |
| 7024 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2342099 times.
|
2342099 | if (!mro) { |
| 7025 | /* Probably ok not to check the call in this case. */ | ||
| 7026 | ✗ | return 1; | |
| 7027 | } | ||
| 7028 | assert(PyTuple_Check(mro)); | ||
| 7029 | |||
| 7030 | /* Find the (base) type that defined the type's slot function. */ | ||
| 7031 | 2342099 | PyTypeObject *defining_type = type; | |
| 7032 | Py_ssize_t i; | ||
| 7033 |
2/2✓ Branch 1 taken 9895740 times.
✓ Branch 2 taken 2342099 times.
|
12237839 | for (i = PyTuple_GET_SIZE(mro) - 1; i >= 0; i--) { |
| 7034 | 9895740 | PyTypeObject *base = _PyType_CAST(PyTuple_GET_ITEM(mro, i)); | |
| 7035 |
2/2✓ Branch 0 taken 5496559 times.
✓ Branch 1 taken 4399181 times.
|
9895740 | if (base->tp_setattro == slot_tp_setattro) { |
| 7036 | /* Ignore Python classes: | ||
| 7037 | they never define their own C-level setattro. */ | ||
| 7038 | } | ||
| 7039 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5496559 times.
|
5496559 | else if (base->tp_setattro == type->tp_setattro) { |
| 7040 | ✗ | defining_type = base; | |
| 7041 | ✗ | break; | |
| 7042 | } | ||
| 7043 | } | ||
| 7044 | |||
| 7045 | /* Reject calls that jump over intermediate C-level overrides. */ | ||
| 7046 |
1/2✓ Branch 0 taken 5269070 times.
✗ Branch 1 not taken.
|
5269070 | for (PyTypeObject *base = defining_type; base; base = base->tp_base) { |
| 7047 |
2/2✓ Branch 0 taken 2342099 times.
✓ Branch 1 taken 2926971 times.
|
5269070 | if (base->tp_setattro == func) { |
| 7048 | /* 'func' is the right slot function to call. */ | ||
| 7049 | 2342099 | break; | |
| 7050 | } | ||
| 7051 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2926971 times.
|
2926971 | else if (base->tp_setattro != slot_tp_setattro) { |
| 7052 | /* 'base' is not a Python class and overrides 'func'. | ||
| 7053 | Its tp_setattro should be called instead. */ | ||
| 7054 | ✗ | PyErr_Format(PyExc_TypeError, | |
| 7055 | "can't apply this %s to %s object", | ||
| 7056 | what, | ||
| 7057 | type->tp_name); | ||
| 7058 | ✗ | return 0; | |
| 7059 | } | ||
| 7060 | } | ||
| 7061 | 2342099 | return 1; | |
| 7062 | } | ||
| 7063 | |||
| 7064 | static PyObject * | ||
| 7065 | 2140286 | wrap_setattr(PyObject *self, PyObject *args, void *wrapped) | |
| 7066 | { | ||
| 7067 | 2140286 | setattrofunc func = (setattrofunc)wrapped; | |
| 7068 | int res; | ||
| 7069 | PyObject *name, *value; | ||
| 7070 | |||
| 7071 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 2140286 times.
|
2140286 | if (!PyArg_UnpackTuple(args, "", 2, 2, &name, &value)) |
| 7072 | ✗ | return NULL; | |
| 7073 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 2140286 times.
|
2140286 | if (!hackcheck(self, func, "__setattr__")) |
| 7074 | ✗ | return NULL; | |
| 7075 | 2140286 | res = (*func)(self, name, value); | |
| 7076 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2140286 times.
|
2140286 | if (res < 0) |
| 7077 | ✗ | return NULL; | |
| 7078 | 2140286 | Py_RETURN_NONE; | |
| 7079 | } | ||
| 7080 | |||
| 7081 | static PyObject * | ||
| 7082 | 201813 | wrap_delattr(PyObject *self, PyObject *args, void *wrapped) | |
| 7083 | { | ||
| 7084 | 201813 | setattrofunc func = (setattrofunc)wrapped; | |
| 7085 | int res; | ||
| 7086 | PyObject *name; | ||
| 7087 | |||
| 7088 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 201813 times.
|
201813 | if (!check_num_args(args, 1)) |
| 7089 | ✗ | return NULL; | |
| 7090 | 201813 | name = PyTuple_GET_ITEM(args, 0); | |
| 7091 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 201813 times.
|
201813 | if (!hackcheck(self, func, "__delattr__")) |
| 7092 | ✗ | return NULL; | |
| 7093 | 201813 | res = (*func)(self, name, NULL); | |
| 7094 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 201813 times.
|
201813 | if (res < 0) |
| 7095 | ✗ | return NULL; | |
| 7096 | 201813 | Py_RETURN_NONE; | |
| 7097 | } | ||
| 7098 | |||
| 7099 | static PyObject * | ||
| 7100 | 3328 | wrap_hashfunc(PyObject *self, PyObject *args, void *wrapped) | |
| 7101 | { | ||
| 7102 | 3328 | hashfunc func = (hashfunc)wrapped; | |
| 7103 | Py_hash_t res; | ||
| 7104 | |||
| 7105 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 3328 times.
|
3328 | if (!check_num_args(args, 0)) |
| 7106 | ✗ | return NULL; | |
| 7107 | 3328 | res = (*func)(self); | |
| 7108 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 3328 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
|
3328 | if (res == -1 && PyErr_Occurred()) |
| 7109 | ✗ | return NULL; | |
| 7110 | 3328 | return PyLong_FromSsize_t(res); | |
| 7111 | } | ||
| 7112 | |||
| 7113 | static PyObject * | ||
| 7114 | 2493 | wrap_call(PyObject *self, PyObject *args, void *wrapped, PyObject *kwds) | |
| 7115 | { | ||
| 7116 | 2493 | ternaryfunc func = (ternaryfunc)wrapped; | |
| 7117 | |||
| 7118 | 2493 | return (*func)(self, args, kwds); | |
| 7119 | } | ||
| 7120 | |||
| 7121 | static PyObject * | ||
| 7122 | ✗ | wrap_del(PyObject *self, PyObject *args, void *wrapped) | |
| 7123 | { | ||
| 7124 | ✗ | destructor func = (destructor)wrapped; | |
| 7125 | |||
| 7126 | ✗ | if (!check_num_args(args, 0)) | |
| 7127 | ✗ | return NULL; | |
| 7128 | |||
| 7129 | ✗ | (*func)(self); | |
| 7130 | ✗ | Py_RETURN_NONE; | |
| 7131 | } | ||
| 7132 | |||
| 7133 | static PyObject * | ||
| 7134 | 39557433 | wrap_richcmpfunc(PyObject *self, PyObject *args, void *wrapped, int op) | |
| 7135 | { | ||
| 7136 | 39557433 | richcmpfunc func = (richcmpfunc)wrapped; | |
| 7137 | PyObject *other; | ||
| 7138 | |||
| 7139 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 39557433 times.
|
39557433 | if (!check_num_args(args, 1)) |
| 7140 | ✗ | return NULL; | |
| 7141 | 39557433 | other = PyTuple_GET_ITEM(args, 0); | |
| 7142 | 39557433 | return (*func)(self, other, op); | |
| 7143 | } | ||
| 7144 | |||
| 7145 | #undef RICHCMP_WRAPPER | ||
| 7146 | #define RICHCMP_WRAPPER(NAME, OP) \ | ||
| 7147 | static PyObject * \ | ||
| 7148 | richcmp_##NAME(PyObject *self, PyObject *args, void *wrapped) \ | ||
| 7149 | { \ | ||
| 7150 | return wrap_richcmpfunc(self, args, wrapped, OP); \ | ||
| 7151 | } | ||
| 7152 | |||
| 7153 | ✗ | RICHCMP_WRAPPER(lt, Py_LT) | |
| 7154 | ✗ | RICHCMP_WRAPPER(le, Py_LE) | |
| 7155 | 32717286 | RICHCMP_WRAPPER(eq, Py_EQ) | |
| 7156 | 6840147 | RICHCMP_WRAPPER(ne, Py_NE) | |
| 7157 | ✗ | RICHCMP_WRAPPER(gt, Py_GT) | |
| 7158 | ✗ | RICHCMP_WRAPPER(ge, Py_GE) | |
| 7159 | |||
| 7160 | static PyObject * | ||
| 7161 | 17168782 | wrap_next(PyObject *self, PyObject *args, void *wrapped) | |
| 7162 | { | ||
| 7163 | 17168782 | unaryfunc func = (unaryfunc)wrapped; | |
| 7164 | PyObject *res; | ||
| 7165 | |||
| 7166 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 17168782 times.
|
17168782 | if (!check_num_args(args, 0)) |
| 7167 | ✗ | return NULL; | |
| 7168 | 17168782 | res = (*func)(self); | |
| 7169 |
3/4✓ Branch 0 taken 10704 times.
✓ Branch 1 taken 17158078 times.
✓ Branch 3 taken 10704 times.
✗ Branch 4 not taken.
|
17168782 | if (res == NULL && !PyErr_Occurred()) |
| 7170 | 10704 | PyErr_SetNone(PyExc_StopIteration); | |
| 7171 | 17168782 | return res; | |
| 7172 | } | ||
| 7173 | |||
| 7174 | static PyObject * | ||
| 7175 | 29274 | wrap_descr_get(PyObject *self, PyObject *args, void *wrapped) | |
| 7176 | { | ||
| 7177 | 29274 | descrgetfunc func = (descrgetfunc)wrapped; | |
| 7178 | PyObject *obj; | ||
| 7179 | 29274 | PyObject *type = NULL; | |
| 7180 | |||
| 7181 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 29274 times.
|
29274 | if (!PyArg_UnpackTuple(args, "", 1, 2, &obj, &type)) |
| 7182 | ✗ | return NULL; | |
| 7183 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 29274 times.
|
29274 | if (obj == Py_None) |
| 7184 | ✗ | obj = NULL; | |
| 7185 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 29274 times.
|
29274 | if (type == Py_None) |
| 7186 | ✗ | type = NULL; | |
| 7187 |
3/4✓ Branch 0 taken 4032 times.
✓ Branch 1 taken 25242 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 4032 times.
|
29274 | if (type == NULL && obj == NULL) { |
| 7188 | ✗ | PyErr_SetString(PyExc_TypeError, | |
| 7189 | "__get__(None, None) is invalid"); | ||
| 7190 | ✗ | return NULL; | |
| 7191 | } | ||
| 7192 | 29274 | return (*func)(self, obj, type); | |
| 7193 | } | ||
| 7194 | |||
| 7195 | static PyObject * | ||
| 7196 | 111 | wrap_descr_set(PyObject *self, PyObject *args, void *wrapped) | |
| 7197 | { | ||
| 7198 | 111 | descrsetfunc func = (descrsetfunc)wrapped; | |
| 7199 | PyObject *obj, *value; | ||
| 7200 | int ret; | ||
| 7201 | |||
| 7202 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 111 times.
|
111 | if (!PyArg_UnpackTuple(args, "", 2, 2, &obj, &value)) |
| 7203 | ✗ | return NULL; | |
| 7204 | 111 | ret = (*func)(self, obj, value); | |
| 7205 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 111 times.
|
111 | if (ret < 0) |
| 7206 | ✗ | return NULL; | |
| 7207 | 111 | Py_RETURN_NONE; | |
| 7208 | } | ||
| 7209 | |||
| 7210 | static PyObject * | ||
| 7211 | ✗ | wrap_descr_delete(PyObject *self, PyObject *args, void *wrapped) | |
| 7212 | { | ||
| 7213 | ✗ | descrsetfunc func = (descrsetfunc)wrapped; | |
| 7214 | PyObject *obj; | ||
| 7215 | int ret; | ||
| 7216 | |||
| 7217 | ✗ | if (!check_num_args(args, 1)) | |
| 7218 | ✗ | return NULL; | |
| 7219 | ✗ | obj = PyTuple_GET_ITEM(args, 0); | |
| 7220 | ✗ | ret = (*func)(self, obj, NULL); | |
| 7221 | ✗ | if (ret < 0) | |
| 7222 | ✗ | return NULL; | |
| 7223 | ✗ | Py_RETURN_NONE; | |
| 7224 | } | ||
| 7225 | |||
| 7226 | static PyObject * | ||
| 7227 | 3504432 | wrap_init(PyObject *self, PyObject *args, void *wrapped, PyObject *kwds) | |
| 7228 | { | ||
| 7229 | 3504432 | initproc func = (initproc)wrapped; | |
| 7230 | |||
| 7231 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 3504432 times.
|
3504432 | if (func(self, args, kwds) < 0) |
| 7232 | ✗ | return NULL; | |
| 7233 | 3504432 | Py_RETURN_NONE; | |
| 7234 | } | ||
| 7235 | |||
| 7236 | static PyObject * | ||
| 7237 | 55820950 | tp_new_wrapper(PyObject *self, PyObject *args, PyObject *kwds) | |
| 7238 | { | ||
| 7239 | PyTypeObject *staticbase; | ||
| 7240 | PyObject *arg0, *res; | ||
| 7241 | |||
| 7242 |
2/4✓ Branch 0 taken 55820950 times.
✗ Branch 1 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 55820950 times.
|
55820950 | if (self == NULL || !PyType_Check(self)) { |
| 7243 | ✗ | PyErr_Format(PyExc_SystemError, | |
| 7244 | "__new__() called with non-type 'self'"); | ||
| 7245 | ✗ | return NULL; | |
| 7246 | } | ||
| 7247 | 55820950 | PyTypeObject *type = (PyTypeObject *)self; | |
| 7248 | |||
| 7249 |
2/4✓ Branch 2 taken 55820950 times.
✗ Branch 3 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 55820950 times.
|
55820950 | if (!PyTuple_Check(args) || PyTuple_GET_SIZE(args) < 1) { |
| 7250 | ✗ | PyErr_Format(PyExc_TypeError, | |
| 7251 | "%s.__new__(): not enough arguments", | ||
| 7252 | type->tp_name); | ||
| 7253 | ✗ | return NULL; | |
| 7254 | } | ||
| 7255 | 55820950 | arg0 = PyTuple_GET_ITEM(args, 0); | |
| 7256 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 55820950 times.
|
55820950 | if (!PyType_Check(arg0)) { |
| 7257 | ✗ | PyErr_Format(PyExc_TypeError, | |
| 7258 | "%s.__new__(X): X is not a type object (%s)", | ||
| 7259 | type->tp_name, | ||
| 7260 | ✗ | Py_TYPE(arg0)->tp_name); | |
| 7261 | ✗ | return NULL; | |
| 7262 | } | ||
| 7263 | 55820950 | PyTypeObject *subtype = (PyTypeObject *)arg0; | |
| 7264 | |||
| 7265 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 55820950 times.
|
55820950 | if (!PyType_IsSubtype(subtype, type)) { |
| 7266 | ✗ | PyErr_Format(PyExc_TypeError, | |
| 7267 | "%s.__new__(%s): %s is not a subtype of %s", | ||
| 7268 | type->tp_name, | ||
| 7269 | subtype->tp_name, | ||
| 7270 | subtype->tp_name, | ||
| 7271 | type->tp_name); | ||
| 7272 | ✗ | return NULL; | |
| 7273 | } | ||
| 7274 | |||
| 7275 | /* Check that the use doesn't do something silly and unsafe like | ||
| 7276 | object.__new__(dict). To do this, we check that the | ||
| 7277 | most derived base that's not a heap type is this type. */ | ||
| 7278 | 55820950 | staticbase = subtype; | |
| 7279 |
3/4✓ Branch 0 taken 120084905 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 64263955 times.
✓ Branch 3 taken 55820950 times.
|
120084905 | while (staticbase && (staticbase->tp_new == slot_tp_new)) |
| 7280 | 64263955 | staticbase = staticbase->tp_base; | |
| 7281 | /* If staticbase is NULL now, it is a really weird type. | ||
| 7282 | In the spirit of backwards compatibility (?), just shut up. */ | ||
| 7283 |
2/4✓ Branch 0 taken 55820950 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 55820950 times.
|
55820950 | if (staticbase && staticbase->tp_new != type->tp_new) { |
| 7284 | ✗ | PyErr_Format(PyExc_TypeError, | |
| 7285 | "%s.__new__(%s) is not safe, use %s.__new__()", | ||
| 7286 | type->tp_name, | ||
| 7287 | subtype->tp_name, | ||
| 7288 | staticbase->tp_name); | ||
| 7289 | ✗ | return NULL; | |
| 7290 | } | ||
| 7291 | |||
| 7292 | 55820950 | args = PyTuple_GetSlice(args, 1, PyTuple_GET_SIZE(args)); | |
| 7293 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 55820950 times.
|
55820950 | if (args == NULL) |
| 7294 | ✗ | return NULL; | |
| 7295 | 55820950 | res = type->tp_new(subtype, args, kwds); | |
| 7296 | 55820950 | Py_DECREF(args); | |
| 7297 | 55820950 | return res; | |
| 7298 | } | ||
| 7299 | |||
| 7300 | static struct PyMethodDef tp_new_methoddef[] = { | ||
| 7301 | {"__new__", _PyCFunction_CAST(tp_new_wrapper), METH_VARARGS|METH_KEYWORDS, | ||
| 7302 | PyDoc_STR("__new__($type, *args, **kwargs)\n--\n\n" | ||
| 7303 | "Create and return a new object. " | ||
| 7304 | "See help(type) for accurate signature.")}, | ||
| 7305 | {0} | ||
| 7306 | }; | ||
| 7307 | |||
| 7308 | static int | ||
| 7309 | 520144 | add_tp_new_wrapper(PyTypeObject *type) | |
| 7310 | { | ||
| 7311 | 520144 | int r = PyDict_Contains(type->tp_dict, &_Py_ID(__new__)); | |
| 7312 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 520144 times.
|
520144 | if (r > 0) { |
| 7313 | ✗ | return 0; | |
| 7314 | } | ||
| 7315 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 520144 times.
|
520144 | if (r < 0) { |
| 7316 | ✗ | return -1; | |
| 7317 | } | ||
| 7318 | |||
| 7319 | 520144 | PyObject *func = PyCFunction_NewEx(tp_new_methoddef, (PyObject *)type, NULL); | |
| 7320 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 520144 times.
|
520144 | if (func == NULL) { |
| 7321 | ✗ | return -1; | |
| 7322 | } | ||
| 7323 | 520144 | r = PyDict_SetItem(type->tp_dict, &_Py_ID(__new__), func); | |
| 7324 | 520144 | Py_DECREF(func); | |
| 7325 | 520144 | return r; | |
| 7326 | } | ||
| 7327 | |||
| 7328 | /* Slot wrappers that call the corresponding __foo__ slot. See comments | ||
| 7329 | below at override_slots() for more explanation. */ | ||
| 7330 | |||
| 7331 | #define SLOT0(FUNCNAME, DUNDER) \ | ||
| 7332 | static PyObject * \ | ||
| 7333 | FUNCNAME(PyObject *self) \ | ||
| 7334 | { \ | ||
| 7335 | PyObject* stack[1] = {self}; \ | ||
| 7336 | return vectorcall_method(&_Py_ID(DUNDER), stack, 1); \ | ||
| 7337 | } | ||
| 7338 | |||
| 7339 | #define SLOT1(FUNCNAME, DUNDER, ARG1TYPE) \ | ||
| 7340 | static PyObject * \ | ||
| 7341 | FUNCNAME(PyObject *self, ARG1TYPE arg1) \ | ||
| 7342 | { \ | ||
| 7343 | PyObject* stack[2] = {self, arg1}; \ | ||
| 7344 | return vectorcall_method(&_Py_ID(DUNDER), stack, 2); \ | ||
| 7345 | } | ||
| 7346 | |||
| 7347 | /* Boolean helper for SLOT1BINFULL(). | ||
| 7348 | right.__class__ is a nontrivial subclass of left.__class__. */ | ||
| 7349 | static int | ||
| 7350 | 1487798 | method_is_overloaded(PyObject *left, PyObject *right, PyObject *name) | |
| 7351 | { | ||
| 7352 | PyObject *a, *b; | ||
| 7353 | int ok; | ||
| 7354 | |||
| 7355 |
1/2✗ Branch 2 not taken.
✓ Branch 3 taken 1487798 times.
|
1487798 | if (_PyObject_LookupAttr((PyObject *)(Py_TYPE(right)), name, &b) < 0) { |
| 7356 | ✗ | return -1; | |
| 7357 | } | ||
| 7358 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1487798 times.
|
1487798 | if (b == NULL) { |
| 7359 | /* If right doesn't have it, it's not overloaded */ | ||
| 7360 | ✗ | return 0; | |
| 7361 | } | ||
| 7362 | |||
| 7363 |
1/2✗ Branch 2 not taken.
✓ Branch 3 taken 1487798 times.
|
1487798 | if (_PyObject_LookupAttr((PyObject *)(Py_TYPE(left)), name, &a) < 0) { |
| 7364 | ✗ | Py_DECREF(b); | |
| 7365 | ✗ | return -1; | |
| 7366 | } | ||
| 7367 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1487798 times.
|
1487798 | if (a == NULL) { |
| 7368 | ✗ | Py_DECREF(b); | |
| 7369 | /* If right has it but left doesn't, it's overloaded */ | ||
| 7370 | ✗ | return 1; | |
| 7371 | } | ||
| 7372 | |||
| 7373 | 1487798 | ok = PyObject_RichCompareBool(a, b, Py_NE); | |
| 7374 | 1487798 | Py_DECREF(a); | |
| 7375 | 1487798 | Py_DECREF(b); | |
| 7376 | 1487798 | return ok; | |
| 7377 | } | ||
| 7378 | |||
| 7379 | |||
| 7380 | #define SLOT1BINFULL(FUNCNAME, TESTFUNC, SLOTNAME, DUNDER, RDUNDER) \ | ||
| 7381 | static PyObject * \ | ||
| 7382 | FUNCNAME(PyObject *self, PyObject *other) \ | ||
| 7383 | { \ | ||
| 7384 | PyObject* stack[2]; \ | ||
| 7385 | PyThreadState *tstate = _PyThreadState_GET(); \ | ||
| 7386 | int do_other = !Py_IS_TYPE(self, Py_TYPE(other)) && \ | ||
| 7387 | Py_TYPE(other)->tp_as_number != NULL && \ | ||
| 7388 | Py_TYPE(other)->tp_as_number->SLOTNAME == TESTFUNC; \ | ||
| 7389 | if (Py_TYPE(self)->tp_as_number != NULL && \ | ||
| 7390 | Py_TYPE(self)->tp_as_number->SLOTNAME == TESTFUNC) { \ | ||
| 7391 | PyObject *r; \ | ||
| 7392 | if (do_other && PyType_IsSubtype(Py_TYPE(other), Py_TYPE(self))) { \ | ||
| 7393 | int ok = method_is_overloaded(self, other, &_Py_ID(RDUNDER)); \ | ||
| 7394 | if (ok < 0) { \ | ||
| 7395 | return NULL; \ | ||
| 7396 | } \ | ||
| 7397 | if (ok) { \ | ||
| 7398 | stack[0] = other; \ | ||
| 7399 | stack[1] = self; \ | ||
| 7400 | r = vectorcall_maybe(tstate, &_Py_ID(RDUNDER), stack, 2); \ | ||
| 7401 | if (r != Py_NotImplemented) \ | ||
| 7402 | return r; \ | ||
| 7403 | Py_DECREF(r); \ | ||
| 7404 | do_other = 0; \ | ||
| 7405 | } \ | ||
| 7406 | } \ | ||
| 7407 | stack[0] = self; \ | ||
| 7408 | stack[1] = other; \ | ||
| 7409 | r = vectorcall_maybe(tstate, &_Py_ID(DUNDER), stack, 2); \ | ||
| 7410 | if (r != Py_NotImplemented || \ | ||
| 7411 | Py_IS_TYPE(other, Py_TYPE(self))) \ | ||
| 7412 | return r; \ | ||
| 7413 | Py_DECREF(r); \ | ||
| 7414 | } \ | ||
| 7415 | if (do_other) { \ | ||
| 7416 | stack[0] = other; \ | ||
| 7417 | stack[1] = self; \ | ||
| 7418 | return vectorcall_maybe(tstate, &_Py_ID(RDUNDER), stack, 2); \ | ||
| 7419 | } \ | ||
| 7420 | Py_RETURN_NOTIMPLEMENTED; \ | ||
| 7421 | } | ||
| 7422 | |||
| 7423 | #define SLOT1BIN(FUNCNAME, SLOTNAME, DUNDER, RDUNDER) \ | ||
| 7424 | SLOT1BINFULL(FUNCNAME, FUNCNAME, SLOTNAME, DUNDER, RDUNDER) | ||
| 7425 | |||
| 7426 | static Py_ssize_t | ||
| 7427 | 6986591 | slot_sq_length(PyObject *self) | |
| 7428 | { | ||
| 7429 | 6986591 | PyObject* stack[1] = {self}; | |
| 7430 | 6986591 | PyObject *res = vectorcall_method(&_Py_ID(__len__), stack, 1); | |
| 7431 | Py_ssize_t len; | ||
| 7432 | |||
| 7433 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6986591 times.
|
6986591 | if (res == NULL) |
| 7434 | ✗ | return -1; | |
| 7435 | |||
| 7436 | 6986591 | Py_SETREF(res, _PyNumber_Index(res)); | |
| 7437 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6986591 times.
|
6986591 | if (res == NULL) |
| 7438 | ✗ | return -1; | |
| 7439 | |||
| 7440 | assert(PyLong_Check(res)); | ||
| 7441 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 6986591 times.
|
6986591 | if (Py_SIZE(res) < 0) { |
| 7442 | ✗ | Py_DECREF(res); | |
| 7443 | ✗ | PyErr_SetString(PyExc_ValueError, | |
| 7444 | "__len__() should return >= 0"); | ||
| 7445 | ✗ | return -1; | |
| 7446 | } | ||
| 7447 | |||
| 7448 | 6986591 | len = PyNumber_AsSsize_t(res, PyExc_OverflowError); | |
| 7449 | assert(len >= 0 || PyErr_ExceptionMatches(PyExc_OverflowError)); | ||
| 7450 | 6986591 | Py_DECREF(res); | |
| 7451 | 6986591 | return len; | |
| 7452 | } | ||
| 7453 | |||
| 7454 | static PyObject * | ||
| 7455 | 11076508 | slot_sq_item(PyObject *self, Py_ssize_t i) | |
| 7456 | { | ||
| 7457 | 11076508 | PyObject *ival = PyLong_FromSsize_t(i); | |
| 7458 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 11076508 times.
|
11076508 | if (ival == NULL) { |
| 7459 | ✗ | return NULL; | |
| 7460 | } | ||
| 7461 | 11076508 | PyObject *stack[2] = {self, ival}; | |
| 7462 | 11076508 | PyObject *retval = vectorcall_method(&_Py_ID(__getitem__), stack, 2); | |
| 7463 | 11076508 | Py_DECREF(ival); | |
| 7464 | 11076508 | return retval; | |
| 7465 | } | ||
| 7466 | |||
| 7467 | static int | ||
| 7468 | ✗ | slot_sq_ass_item(PyObject *self, Py_ssize_t index, PyObject *value) | |
| 7469 | { | ||
| 7470 | PyObject *stack[3]; | ||
| 7471 | PyObject *res; | ||
| 7472 | PyObject *index_obj; | ||
| 7473 | |||
| 7474 | ✗ | index_obj = PyLong_FromSsize_t(index); | |
| 7475 | ✗ | if (index_obj == NULL) { | |
| 7476 | ✗ | return -1; | |
| 7477 | } | ||
| 7478 | |||
| 7479 | ✗ | stack[0] = self; | |
| 7480 | ✗ | stack[1] = index_obj; | |
| 7481 | ✗ | if (value == NULL) { | |
| 7482 | ✗ | res = vectorcall_method(&_Py_ID(__delitem__), stack, 2); | |
| 7483 | } | ||
| 7484 | else { | ||
| 7485 | ✗ | stack[2] = value; | |
| 7486 | ✗ | res = vectorcall_method(&_Py_ID(__setitem__), stack, 3); | |
| 7487 | } | ||
| 7488 | ✗ | Py_DECREF(index_obj); | |
| 7489 | |||
| 7490 | ✗ | if (res == NULL) { | |
| 7491 | ✗ | return -1; | |
| 7492 | } | ||
| 7493 | ✗ | Py_DECREF(res); | |
| 7494 | ✗ | return 0; | |
| 7495 | } | ||
| 7496 | |||
| 7497 | static int | ||
| 7498 | 17401096 | slot_sq_contains(PyObject *self, PyObject *value) | |
| 7499 | { | ||
| 7500 | 17401096 | PyThreadState *tstate = _PyThreadState_GET(); | |
| 7501 | PyObject *func, *res; | ||
| 7502 | 17401096 | int result = -1, unbound; | |
| 7503 | |||
| 7504 | 17401096 | func = lookup_maybe_method(self, &_Py_ID(__contains__), &unbound); | |
| 7505 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 17401096 times.
|
17401096 | if (func == Py_None) { |
| 7506 | ✗ | Py_DECREF(func); | |
| 7507 | ✗ | PyErr_Format(PyExc_TypeError, | |
| 7508 | "'%.200s' object is not a container", | ||
| 7509 | ✗ | Py_TYPE(self)->tp_name); | |
| 7510 | ✗ | return -1; | |
| 7511 | } | ||
| 7512 |
1/2✓ Branch 0 taken 17401096 times.
✗ Branch 1 not taken.
|
17401096 | if (func != NULL) { |
| 7513 | 17401096 | PyObject *args[2] = {self, value}; | |
| 7514 | 17401096 | res = vectorcall_unbound(tstate, unbound, func, args, 2); | |
| 7515 | 17401096 | Py_DECREF(func); | |
| 7516 |
1/2✓ Branch 0 taken 17401096 times.
✗ Branch 1 not taken.
|
17401096 | if (res != NULL) { |
| 7517 | 17401096 | result = PyObject_IsTrue(res); | |
| 7518 | 17401096 | Py_DECREF(res); | |
| 7519 | } | ||
| 7520 | } | ||
| 7521 | ✗ | else if (! PyErr_Occurred()) { | |
| 7522 | /* Possible results: -1 and 1 */ | ||
| 7523 | ✗ | result = (int)_PySequence_IterSearch(self, value, | |
| 7524 | PY_ITERSEARCH_CONTAINS); | ||
| 7525 | } | ||
| 7526 | 17401096 | return result; | |
| 7527 | } | ||
| 7528 | |||
| 7529 | #define slot_mp_length slot_sq_length | ||
| 7530 | |||
| 7531 | 24334859 | SLOT1(slot_mp_subscript, __getitem__, PyObject *) | |
| 7532 | |||
| 7533 | static int | ||
| 7534 | 11996279 | slot_mp_ass_subscript(PyObject *self, PyObject *key, PyObject *value) | |
| 7535 | { | ||
| 7536 | PyObject *stack[3]; | ||
| 7537 | PyObject *res; | ||
| 7538 | |||
| 7539 | 11996279 | stack[0] = self; | |
| 7540 | 11996279 | stack[1] = key; | |
| 7541 |
2/2✓ Branch 0 taken 72572 times.
✓ Branch 1 taken 11923707 times.
|
11996279 | if (value == NULL) { |
| 7542 | 72572 | res = vectorcall_method(&_Py_ID(__delitem__), stack, 2); | |
| 7543 | } | ||
| 7544 | else { | ||
| 7545 | 11923707 | stack[2] = value; | |
| 7546 | 11923707 | res = vectorcall_method(&_Py_ID(__setitem__), stack, 3); | |
| 7547 | } | ||
| 7548 | |||
| 7549 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 11996279 times.
|
11996279 | if (res == NULL) |
| 7550 | ✗ | return -1; | |
| 7551 | 11996279 | Py_DECREF(res); | |
| 7552 | 11996279 | return 0; | |
| 7553 | } | ||
| 7554 | |||
| 7555 |
16/26✓ Branch 3 taken 540253 times.
✓ Branch 4 taken 32403531 times.
✓ Branch 6 taken 540253 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 475997 times.
✓ Branch 10 taken 64256 times.
✓ Branch 12 taken 32943784 times.
✗ Branch 13 not taken.
✓ Branch 15 taken 32940541 times.
✓ Branch 16 taken 3243 times.
✓ Branch 17 taken 472754 times.
✓ Branch 18 taken 32467787 times.
✓ Branch 22 taken 32 times.
✓ Branch 23 taken 472722 times.
✗ Branch 25 not taken.
✓ Branch 26 taken 32 times.
✗ Branch 27 not taken.
✓ Branch 28 taken 32 times.
✗ Branch 30 not taken.
✗ Branch 31 not taken.
✗ Branch 34 not taken.
✓ Branch 35 taken 32940541 times.
✗ Branch 38 not taken.
✗ Branch 39 not taken.
✓ Branch 41 taken 3243 times.
✗ Branch 42 not taken.
|
32943784 | SLOT1BIN(slot_nb_add, nb_add, __add__, __radd__) |
| 7556 |
16/26✓ Branch 3 taken 322664 times.
✓ Branch 4 taken 24210344 times.
✓ Branch 6 taken 322664 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 308923 times.
✓ Branch 10 taken 13741 times.
✓ Branch 12 taken 24533008 times.
✗ Branch 13 not taken.
✓ Branch 15 taken 24225652 times.
✓ Branch 16 taken 307356 times.
✓ Branch 17 taken 1567 times.
✓ Branch 18 taken 24224085 times.
✓ Branch 22 taken 336 times.
✓ Branch 23 taken 1231 times.
✗ Branch 25 not taken.
✓ Branch 26 taken 336 times.
✗ Branch 27 not taken.
✓ Branch 28 taken 336 times.
✗ Branch 30 not taken.
✗ Branch 31 not taken.
✗ Branch 34 not taken.
✓ Branch 35 taken 24225652 times.
✗ Branch 38 not taken.
✗ Branch 39 not taken.
✓ Branch 41 taken 307356 times.
✗ Branch 42 not taken.
|
24533008 | SLOT1BIN(slot_nb_subtract, nb_subtract, __sub__, __rsub__) |
| 7557 |
19/26✓ Branch 3 taken 2611648 times.
✓ Branch 4 taken 1251966 times.
✓ Branch 6 taken 2610787 times.
✓ Branch 7 taken 861 times.
✓ Branch 9 taken 2103285 times.
✓ Branch 10 taken 507502 times.
✓ Branch 12 taken 3863614 times.
✗ Branch 13 not taken.
✓ Branch 15 taken 3860413 times.
✓ Branch 16 taken 3201 times.
✓ Branch 17 taken 2100084 times.
✓ Branch 18 taken 1760329 times.
✓ Branch 22 taken 1419768 times.
✓ Branch 23 taken 680316 times.
✗ Branch 25 not taken.
✓ Branch 26 taken 1419768 times.
✓ Branch 27 taken 525 times.
✓ Branch 28 taken 1419243 times.
✓ Branch 30 taken 525 times.
✗ Branch 31 not taken.
✗ Branch 34 not taken.
✓ Branch 35 taken 3859888 times.
✗ Branch 38 not taken.
✗ Branch 39 not taken.
✓ Branch 41 taken 3201 times.
✗ Branch 42 not taken.
|
3863614 | SLOT1BIN(slot_nb_multiply, nb_multiply, __mul__, __rmul__) |
| 7558 | ✗ | SLOT1BIN(slot_nb_matrix_multiply, nb_matrix_multiply, __matmul__, __rmatmul__) | |
| 7559 |
7/26✓ Branch 3 taken 1197 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 1197 times.
✗ Branch 7 not taken.
✗ Branch 9 not taken.
✓ Branch 10 taken 1197 times.
✓ Branch 12 taken 1197 times.
✗ Branch 13 not taken.
✓ Branch 15 taken 1197 times.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✓ Branch 18 taken 1197 times.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
✗ Branch 25 not taken.
✗ Branch 26 not taken.
✗ Branch 27 not taken.
✗ Branch 28 not taken.
✗ Branch 30 not taken.
✗ Branch 31 not taken.
✗ Branch 34 not taken.
✓ Branch 35 taken 1197 times.
✗ Branch 38 not taken.
✗ Branch 39 not taken.
✗ Branch 41 not taken.
✗ Branch 42 not taken.
|
1197 | SLOT1BIN(slot_nb_remainder, nb_remainder, __mod__, __rmod__) |
| 7560 |
8/26✓ Branch 3 taken 1197 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 1197 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 1197 times.
✗ Branch 10 not taken.
✓ Branch 12 taken 1197 times.
✗ Branch 13 not taken.
✓ Branch 15 taken 1197 times.
✗ Branch 16 not taken.
✓ Branch 17 taken 1197 times.
✗ Branch 18 not taken.
✗ Branch 22 not taken.
✓ Branch 23 taken 1197 times.
✗ Branch 25 not taken.
✗ Branch 26 not taken.
✗ Branch 27 not taken.
✗ Branch 28 not taken.
✗ Branch 30 not taken.
✗ Branch 31 not taken.
✗ Branch 34 not taken.
✓ Branch 35 taken 1197 times.
✗ Branch 38 not taken.
✗ Branch 39 not taken.
✗ Branch 41 not taken.
✗ Branch 42 not taken.
|
1197 | SLOT1BIN(slot_nb_divmod, nb_divmod, __divmod__, __rdivmod__) |
| 7561 | |||
| 7562 | static PyObject *slot_nb_power(PyObject *, PyObject *, PyObject *); | ||
| 7563 | |||
| 7564 |
14/26✓ Branch 3 taken 74929 times.
✓ Branch 4 taken 756 times.
✓ Branch 6 taken 74929 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 71715 times.
✓ Branch 10 taken 3214 times.
✓ Branch 12 taken 75685 times.
✗ Branch 13 not taken.
✓ Branch 15 taken 75685 times.
✗ Branch 16 not taken.
✓ Branch 17 taken 71715 times.
✓ Branch 18 taken 3970 times.
✓ Branch 22 taken 67662 times.
✓ Branch 23 taken 4053 times.
✗ Branch 25 not taken.
✓ Branch 26 taken 67662 times.
✗ Branch 27 not taken.
✓ Branch 28 taken 67662 times.
✗ Branch 30 not taken.
✗ Branch 31 not taken.
✗ Branch 34 not taken.
✓ Branch 35 taken 75685 times.
✗ Branch 38 not taken.
✗ Branch 39 not taken.
✗ Branch 41 not taken.
✗ Branch 42 not taken.
|
75685 | SLOT1BINFULL(slot_nb_power_binary, slot_nb_power, nb_power, __pow__, __rpow__) |
| 7565 | |||
| 7566 | static PyObject * | ||
| 7567 | 75685 | slot_nb_power(PyObject *self, PyObject *other, PyObject *modulus) | |
| 7568 | { | ||
| 7569 |
1/2✓ Branch 0 taken 75685 times.
✗ Branch 1 not taken.
|
75685 | if (modulus == Py_None) |
| 7570 | 75685 | return slot_nb_power_binary(self, other); | |
| 7571 | /* Three-arg power doesn't use __rpow__. But ternary_op | ||
| 7572 | can call this when the second argument's type uses | ||
| 7573 | slot_nb_power, so check before calling self.__pow__. */ | ||
| 7574 | ✗ | if (Py_TYPE(self)->tp_as_number != NULL && | |
| 7575 | ✗ | Py_TYPE(self)->tp_as_number->nb_power == slot_nb_power) { | |
| 7576 | ✗ | PyObject* stack[3] = {self, other, modulus}; | |
| 7577 | ✗ | return vectorcall_method(&_Py_ID(__pow__), stack, 3); | |
| 7578 | } | ||
| 7579 | ✗ | Py_RETURN_NOTIMPLEMENTED; | |
| 7580 | } | ||
| 7581 | |||
| 7582 | 317447 | SLOT0(slot_nb_negative, __neg__) | |
| 7583 | ✗ | SLOT0(slot_nb_positive, __pos__) | |
| 7584 | 6825 | SLOT0(slot_nb_absolute, __abs__) | |
| 7585 | |||
| 7586 | static int | ||
| 7587 | 2449327 | slot_nb_bool(PyObject *self) | |
| 7588 | { | ||
| 7589 | PyObject *func, *value; | ||
| 7590 | int result, unbound; | ||
| 7591 | 2449327 | int using_len = 0; | |
| 7592 | |||
| 7593 | 2449327 | func = lookup_maybe_method(self, &_Py_ID(__bool__), &unbound); | |
| 7594 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2449327 times.
|
2449327 | if (func == NULL) { |
| 7595 | ✗ | if (PyErr_Occurred()) { | |
| 7596 | ✗ | return -1; | |
| 7597 | } | ||
| 7598 | |||
| 7599 | ✗ | func = lookup_maybe_method(self, &_Py_ID(__len__), &unbound); | |
| 7600 | ✗ | if (func == NULL) { | |
| 7601 | ✗ | if (PyErr_Occurred()) { | |
| 7602 | ✗ | return -1; | |
| 7603 | } | ||
| 7604 | ✗ | return 1; | |
| 7605 | } | ||
| 7606 | ✗ | using_len = 1; | |
| 7607 | } | ||
| 7608 | |||
| 7609 | 2449327 | value = call_unbound_noarg(unbound, func, self); | |
| 7610 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2449327 times.
|
2449327 | if (value == NULL) { |
| 7611 | ✗ | goto error; | |
| 7612 | } | ||
| 7613 | |||
| 7614 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2449327 times.
|
2449327 | if (using_len) { |
| 7615 | /* bool type enforced by slot_nb_len */ | ||
| 7616 | ✗ | result = PyObject_IsTrue(value); | |
| 7617 | } | ||
| 7618 |
1/2✓ Branch 1 taken 2449327 times.
✗ Branch 2 not taken.
|
2449327 | else if (PyBool_Check(value)) { |
| 7619 | 2449327 | result = PyObject_IsTrue(value); | |
| 7620 | } | ||
| 7621 | else { | ||
| 7622 | ✗ | PyErr_Format(PyExc_TypeError, | |
| 7623 | "__bool__ should return " | ||
| 7624 | "bool, returned %s", | ||
| 7625 | ✗ | Py_TYPE(value)->tp_name); | |
| 7626 | ✗ | result = -1; | |
| 7627 | } | ||
| 7628 | |||
| 7629 | 2449327 | Py_DECREF(value); | |
| 7630 | 2449327 | Py_DECREF(func); | |
| 7631 | 2449327 | return result; | |
| 7632 | |||
| 7633 | ✗ | error: | |
| 7634 | ✗ | Py_DECREF(func); | |
| 7635 | ✗ | return -1; | |
| 7636 | } | ||
| 7637 | |||
| 7638 | |||
| 7639 | static PyObject * | ||
| 7640 | 683 | slot_nb_index(PyObject *self) | |
| 7641 | { | ||
| 7642 | 683 | PyObject *stack[1] = {self}; | |
| 7643 | 683 | return vectorcall_method(&_Py_ID(__index__), stack, 1); | |
| 7644 | } | ||
| 7645 | |||
| 7646 | |||
| 7647 | 861 | SLOT0(slot_nb_invert, __invert__) | |
| 7648 |
7/26✓ Branch 3 taken 287 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 287 times.
✗ Branch 7 not taken.
✗ Branch 9 not taken.
✓ Branch 10 taken 287 times.
✓ Branch 12 taken 287 times.
✗ Branch 13 not taken.
✓ Branch 15 taken 287 times.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✓ Branch 18 taken 287 times.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
✗ Branch 25 not taken.
✗ Branch 26 not taken.
✗ Branch 27 not taken.
✗ Branch 28 not taken.
✗ Branch 30 not taken.
✗ Branch 31 not taken.
✗ Branch 34 not taken.
✓ Branch 35 taken 287 times.
✗ Branch 38 not taken.
✗ Branch 39 not taken.
✗ Branch 41 not taken.
✗ Branch 42 not taken.
|
287 | SLOT1BIN(slot_nb_lshift, nb_lshift, __lshift__, __rlshift__) |
| 7649 | ✗ | SLOT1BIN(slot_nb_rshift, nb_rshift, __rshift__, __rrshift__) | |
| 7650 |
10/26✓ Branch 3 taken 789762 times.
✓ Branch 4 taken 332 times.
✓ Branch 6 taken 789762 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 789762 times.
✗ Branch 10 not taken.
✓ Branch 12 taken 790094 times.
✗ Branch 13 not taken.
✓ Branch 15 taken 332 times.
✓ Branch 16 taken 789762 times.
✗ Branch 17 not taken.
✓ Branch 18 taken 332 times.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
✗ Branch 25 not taken.
✗ Branch 26 not taken.
✗ Branch 27 not taken.
✗ Branch 28 not taken.
✗ Branch 30 not taken.
✗ Branch 31 not taken.
✗ Branch 34 not taken.
✓ Branch 35 taken 332 times.
✗ Branch 38 not taken.
✗ Branch 39 not taken.
✓ Branch 41 taken 789762 times.
✗ Branch 42 not taken.
|
790094 | SLOT1BIN(slot_nb_and, nb_and, __and__, __rand__) |
| 7651 |
5/26✗ Branch 3 not taken.
✓ Branch 4 taken 287 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✓ Branch 12 taken 287 times.
✗ Branch 13 not taken.
✓ Branch 15 taken 287 times.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✓ Branch 18 taken 287 times.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
✗ Branch 25 not taken.
✗ Branch 26 not taken.
✗ Branch 27 not taken.
✗ Branch 28 not taken.
✗ Branch 30 not taken.
✗ Branch 31 not taken.
✗ Branch 34 not taken.
✓ Branch 35 taken 287 times.
✗ Branch 38 not taken.
✗ Branch 39 not taken.
✗ Branch 41 not taken.
✗ Branch 42 not taken.
|
287 | SLOT1BIN(slot_nb_xor, nb_xor, __xor__, __rxor__) |
| 7652 |
14/26✓ Branch 3 taken 10807 times.
✓ Branch 4 taken 25496 times.
✓ Branch 6 taken 10723 times.
✓ Branch 7 taken 84 times.
✓ Branch 9 taken 10436 times.
✓ Branch 10 taken 287 times.
✓ Branch 12 taken 36303 times.
✗ Branch 13 not taken.
✓ Branch 15 taken 35625 times.
✓ Branch 16 taken 678 times.
✓ Branch 17 taken 9758 times.
✓ Branch 18 taken 25867 times.
✗ Branch 22 not taken.
✓ Branch 23 taken 9758 times.
✗ Branch 25 not taken.
✗ Branch 26 not taken.
✗ Branch 27 not taken.
✗ Branch 28 not taken.
✗ Branch 30 not taken.
✗ Branch 31 not taken.
✗ Branch 34 not taken.
✓ Branch 35 taken 35625 times.
✗ Branch 38 not taken.
✗ Branch 39 not taken.
✓ Branch 41 taken 678 times.
✗ Branch 42 not taken.
|
36303 | SLOT1BIN(slot_nb_or, nb_or, __or__, __ror__) |
| 7653 | |||
| 7654 | 24728 | SLOT0(slot_nb_int, __int__) | |
| 7655 | 1772309 | SLOT0(slot_nb_float, __float__) | |
| 7656 | 618214 | SLOT1(slot_nb_inplace_add, __iadd__, PyObject *) | |
| 7657 | ✗ | SLOT1(slot_nb_inplace_subtract, __isub__, PyObject *) | |
| 7658 | ✗ | SLOT1(slot_nb_inplace_multiply, __imul__, PyObject *) | |
| 7659 | ✗ | SLOT1(slot_nb_inplace_matrix_multiply, __imatmul__, PyObject *) | |
| 7660 | ✗ | SLOT1(slot_nb_inplace_remainder, __imod__, PyObject *) | |
| 7661 | /* Can't use SLOT1 here, because nb_inplace_power is ternary */ | ||
| 7662 | static PyObject * | ||
| 7663 | ✗ | slot_nb_inplace_power(PyObject *self, PyObject * arg1, PyObject *arg2) | |
| 7664 | { | ||
| 7665 | ✗ | PyObject *stack[2] = {self, arg1}; | |
| 7666 | ✗ | return vectorcall_method(&_Py_ID(__ipow__), stack, 2); | |
| 7667 | } | ||
| 7668 | ✗ | SLOT1(slot_nb_inplace_lshift, __ilshift__, PyObject *) | |
| 7669 | ✗ | SLOT1(slot_nb_inplace_rshift, __irshift__, PyObject *) | |
| 7670 | ✗ | SLOT1(slot_nb_inplace_and, __iand__, PyObject *) | |
| 7671 | ✗ | SLOT1(slot_nb_inplace_xor, __ixor__, PyObject *) | |
| 7672 | ✗ | SLOT1(slot_nb_inplace_or, __ior__, PyObject *) | |
| 7673 | ✗ | SLOT1BIN(slot_nb_floor_divide, nb_floor_divide, | |
| 7674 | __floordiv__, __rfloordiv__) | ||
| 7675 |
13/26✓ Branch 3 taken 1025472 times.
✓ Branch 4 taken 3171 times.
✓ Branch 6 taken 1025472 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 395873 times.
✓ Branch 10 taken 629599 times.
✓ Branch 12 taken 1028643 times.
✗ Branch 13 not taken.
✓ Branch 15 taken 1022467 times.
✓ Branch 16 taken 6176 times.
✓ Branch 17 taken 389697 times.
✓ Branch 18 taken 632770 times.
✗ Branch 22 not taken.
✓ Branch 23 taken 389697 times.
✗ Branch 25 not taken.
✗ Branch 26 not taken.
✗ Branch 27 not taken.
✗ Branch 28 not taken.
✗ Branch 30 not taken.
✗ Branch 31 not taken.
✗ Branch 34 not taken.
✓ Branch 35 taken 1022467 times.
✗ Branch 38 not taken.
✗ Branch 39 not taken.
✓ Branch 41 taken 6176 times.
✗ Branch 42 not taken.
|
1028643 | SLOT1BIN(slot_nb_true_divide, nb_true_divide, __truediv__, __rtruediv__) |
| 7676 | ✗ | SLOT1(slot_nb_inplace_floor_divide, __ifloordiv__, PyObject *) | |
| 7677 | ✗ | SLOT1(slot_nb_inplace_true_divide, __itruediv__, PyObject *) | |
| 7678 | |||
| 7679 | static PyObject * | ||
| 7680 | 71302 | slot_tp_repr(PyObject *self) | |
| 7681 | { | ||
| 7682 | PyObject *func, *res; | ||
| 7683 | int unbound; | ||
| 7684 | |||
| 7685 | 71302 | func = lookup_maybe_method(self, &_Py_ID(__repr__), &unbound); | |
| 7686 |
1/2✓ Branch 0 taken 71302 times.
✗ Branch 1 not taken.
|
71302 | if (func != NULL) { |
| 7687 | 71302 | res = call_unbound_noarg(unbound, func, self); | |
| 7688 | 71302 | Py_DECREF(func); | |
| 7689 | 71302 | return res; | |
| 7690 | } | ||
| 7691 | ✗ | PyErr_Clear(); | |
| 7692 | ✗ | return PyUnicode_FromFormat("<%s object at %p>", | |
| 7693 | ✗ | Py_TYPE(self)->tp_name, self); | |
| 7694 | } | ||
| 7695 | |||
| 7696 | 1903625 | SLOT0(slot_tp_str, __str__) | |
| 7697 | |||
| 7698 | static Py_hash_t | ||
| 7699 | 31759775 | slot_tp_hash(PyObject *self) | |
| 7700 | { | ||
| 7701 | PyObject *func, *res; | ||
| 7702 | Py_ssize_t h; | ||
| 7703 | int unbound; | ||
| 7704 | |||
| 7705 | 31759775 | func = lookup_maybe_method(self, &_Py_ID(__hash__), &unbound); | |
| 7706 | |||
| 7707 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 31759775 times.
|
31759775 | if (func == Py_None) { |
| 7708 | ✗ | Py_DECREF(func); | |
| 7709 | ✗ | func = NULL; | |
| 7710 | } | ||
| 7711 | |||
| 7712 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 31759775 times.
|
31759775 | if (func == NULL) { |
| 7713 | ✗ | return PyObject_HashNotImplemented(self); | |
| 7714 | } | ||
| 7715 | |||
| 7716 | 31759775 | res = call_unbound_noarg(unbound, func, self); | |
| 7717 | 31759775 | Py_DECREF(func); | |
| 7718 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 31759775 times.
|
31759775 | if (res == NULL) |
| 7719 | ✗ | return -1; | |
| 7720 | |||
| 7721 |
1/2✗ Branch 2 not taken.
✓ Branch 3 taken 31759775 times.
|
31759775 | if (!PyLong_Check(res)) { |
| 7722 | ✗ | PyErr_SetString(PyExc_TypeError, | |
| 7723 | "__hash__ method should return an integer"); | ||
| 7724 | ✗ | return -1; | |
| 7725 | } | ||
| 7726 | /* Transform the PyLong `res` to a Py_hash_t `h`. For an existing | ||
| 7727 | hashable Python object x, hash(x) will always lie within the range of | ||
| 7728 | Py_hash_t. Therefore our transformation must preserve values that | ||
| 7729 | already lie within this range, to ensure that if x.__hash__() returns | ||
| 7730 | hash(y) then hash(x) == hash(y). */ | ||
| 7731 | 31759775 | h = PyLong_AsSsize_t(res); | |
| 7732 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 31759775 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
|
31759775 | if (h == -1 && PyErr_Occurred()) { |
| 7733 | /* res was not within the range of a Py_hash_t, so we're free to | ||
| 7734 | use any sufficiently bit-mixing transformation; | ||
| 7735 | long.__hash__ will do nicely. */ | ||
| 7736 | ✗ | PyErr_Clear(); | |
| 7737 | ✗ | h = PyLong_Type.tp_hash(res); | |
| 7738 | } | ||
| 7739 | /* -1 is reserved for errors. */ | ||
| 7740 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 31759775 times.
|
31759775 | if (h == -1) |
| 7741 | ✗ | h = -2; | |
| 7742 | 31759775 | Py_DECREF(res); | |
| 7743 | 31759775 | return h; | |
| 7744 | } | ||
| 7745 | |||
| 7746 | static PyObject * | ||
| 7747 | 2613077 | slot_tp_call(PyObject *self, PyObject *args, PyObject *kwds) | |
| 7748 | { | ||
| 7749 | 2613077 | PyThreadState *tstate = _PyThreadState_GET(); | |
| 7750 | int unbound; | ||
| 7751 | |||
| 7752 | 2613077 | PyObject *meth = lookup_method(self, &_Py_ID(__call__), &unbound); | |
| 7753 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2613077 times.
|
2613077 | if (meth == NULL) { |
| 7754 | ✗ | return NULL; | |
| 7755 | } | ||
| 7756 | |||
| 7757 | PyObject *res; | ||
| 7758 |
2/2✓ Branch 0 taken 2598190 times.
✓ Branch 1 taken 14887 times.
|
2613077 | if (unbound) { |
| 7759 | 2598190 | res = _PyObject_Call_Prepend(tstate, meth, self, args, kwds); | |
| 7760 | } | ||
| 7761 | else { | ||
| 7762 | 14887 | res = _PyObject_Call(tstate, meth, args, kwds); | |
| 7763 | } | ||
| 7764 | |||
| 7765 | 2613077 | Py_DECREF(meth); | |
| 7766 | 2613077 | return res; | |
| 7767 | } | ||
| 7768 | |||
| 7769 | /* There are two slot dispatch functions for tp_getattro. | ||
| 7770 | |||
| 7771 | - slot_tp_getattro() is used when __getattribute__ is overridden | ||
| 7772 | but no __getattr__ hook is present; | ||
| 7773 | |||
| 7774 | - slot_tp_getattr_hook() is used when a __getattr__ hook is present. | ||
| 7775 | |||
| 7776 | The code in update_one_slot() always installs slot_tp_getattr_hook(); this | ||
| 7777 | detects the absence of __getattr__ and then installs the simpler slot if | ||
| 7778 | necessary. */ | ||
| 7779 | |||
| 7780 | static PyObject * | ||
| 7781 | 2736 | slot_tp_getattro(PyObject *self, PyObject *name) | |
| 7782 | { | ||
| 7783 | 2736 | PyObject *stack[2] = {self, name}; | |
| 7784 | 2736 | return vectorcall_method(&_Py_ID(__getattribute__), stack, 2); | |
| 7785 | } | ||
| 7786 | |||
| 7787 | static inline PyObject * | ||
| 7788 | 5565035 | call_attribute(PyObject *self, PyObject *attr, PyObject *name) | |
| 7789 | { | ||
| 7790 | 5565035 | PyObject *res, *descr = NULL; | |
| 7791 | |||
| 7792 |
1/2✓ Branch 2 taken 5565035 times.
✗ Branch 3 not taken.
|
5565035 | if (_PyType_HasFeature(Py_TYPE(attr), Py_TPFLAGS_METHOD_DESCRIPTOR)) { |
| 7793 | 5565035 | PyObject *args[] = { self, name }; | |
| 7794 | 5565035 | res = PyObject_Vectorcall(attr, args, 2, NULL); | |
| 7795 | 5565035 | return res; | |
| 7796 | } | ||
| 7797 | |||
| 7798 | ✗ | descrgetfunc f = Py_TYPE(attr)->tp_descr_get; | |
| 7799 | |||
| 7800 | ✗ | if (f != NULL) { | |
| 7801 | ✗ | descr = f(attr, self, (PyObject *)(Py_TYPE(self))); | |
| 7802 | ✗ | if (descr == NULL) | |
| 7803 | ✗ | return NULL; | |
| 7804 | else | ||
| 7805 | ✗ | attr = descr; | |
| 7806 | } | ||
| 7807 | ✗ | res = PyObject_CallOneArg(attr, name); | |
| 7808 | ✗ | Py_XDECREF(descr); | |
| 7809 | ✗ | return res; | |
| 7810 | } | ||
| 7811 | |||
| 7812 | static PyObject * | ||
| 7813 | 46712275 | slot_tp_getattr_hook(PyObject *self, PyObject *name) | |
| 7814 | { | ||
| 7815 | 46712275 | PyTypeObject *tp = Py_TYPE(self); | |
| 7816 | PyObject *getattr, *getattribute, *res; | ||
| 7817 | |||
| 7818 | /* speed hack: we could use lookup_maybe, but that would resolve the | ||
| 7819 | method fully for each attribute lookup for classes with | ||
| 7820 | __getattr__, even when the attribute is present. So we use | ||
| 7821 | _PyType_Lookup and create the method only when needed, with | ||
| 7822 | call_attribute. */ | ||
| 7823 | 46712275 | getattr = _PyType_Lookup(tp, &_Py_ID(__getattr__)); | |
| 7824 |
2/2✓ Branch 0 taken 663 times.
✓ Branch 1 taken 46711612 times.
|
46712275 | if (getattr == NULL) { |
| 7825 | /* No __getattr__ hook: use a simpler dispatcher */ | ||
| 7826 | 663 | tp->tp_getattro = slot_tp_getattro; | |
| 7827 | 663 | return slot_tp_getattro(self, name); | |
| 7828 | } | ||
| 7829 | 46711612 | Py_INCREF(getattr); | |
| 7830 | /* speed hack: we could use lookup_maybe, but that would resolve the | ||
| 7831 | method fully for each attribute lookup for classes with | ||
| 7832 | __getattr__, even when self has the default __getattribute__ | ||
| 7833 | method. So we use _PyType_Lookup and create the method only when | ||
| 7834 | needed, with call_attribute. */ | ||
| 7835 | 46711612 | getattribute = _PyType_Lookup(tp, &_Py_ID(__getattribute__)); | |
| 7836 |
2/4✓ Branch 0 taken 46711612 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 46711612 times.
✗ Branch 3 not taken.
|
93423224 | if (getattribute == NULL || |
| 7837 | 46711612 | (Py_IS_TYPE(getattribute, &PyWrapperDescr_Type) && | |
| 7838 |
2/2✓ Branch 0 taken 42574332 times.
✓ Branch 1 taken 4137280 times.
|
46711612 | ((PyWrapperDescrObject *)getattribute)->d_wrapped == |
| 7839 | (void *)PyObject_GenericGetAttr)) | ||
| 7840 | 42574332 | res = PyObject_GenericGetAttr(self, name); | |
| 7841 | else { | ||
| 7842 | 4137280 | Py_INCREF(getattribute); | |
| 7843 | 4137280 | res = call_attribute(self, getattribute, name); | |
| 7844 | 4137280 | Py_DECREF(getattribute); | |
| 7845 | } | ||
| 7846 |
3/4✓ Branch 0 taken 1427755 times.
✓ Branch 1 taken 45283857 times.
✓ Branch 3 taken 1427755 times.
✗ Branch 4 not taken.
|
46711612 | if (res == NULL && PyErr_ExceptionMatches(PyExc_AttributeError)) { |
| 7847 | 1427755 | PyErr_Clear(); | |
| 7848 | 1427755 | res = call_attribute(self, getattr, name); | |
| 7849 | } | ||
| 7850 | 46711612 | Py_DECREF(getattr); | |
| 7851 | 46711612 | return res; | |
| 7852 | } | ||
| 7853 | |||
| 7854 | static int | ||
| 7855 | 2340999 | slot_tp_setattro(PyObject *self, PyObject *name, PyObject *value) | |
| 7856 | { | ||
| 7857 | PyObject *stack[3]; | ||
| 7858 | PyObject *res; | ||
| 7859 | |||
| 7860 | 2340999 | stack[0] = self; | |
| 7861 | 2340999 | stack[1] = name; | |
| 7862 |
2/2✓ Branch 0 taken 201813 times.
✓ Branch 1 taken 2139186 times.
|
2340999 | if (value == NULL) { |
| 7863 | 201813 | res = vectorcall_method(&_Py_ID(__delattr__), stack, 2); | |
| 7864 | } | ||
| 7865 | else { | ||
| 7866 | 2139186 | stack[2] = value; | |
| 7867 | 2139186 | res = vectorcall_method(&_Py_ID(__setattr__), stack, 3); | |
| 7868 | } | ||
| 7869 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2340999 times.
|
2340999 | if (res == NULL) |
| 7870 | ✗ | return -1; | |
| 7871 | 2340999 | Py_DECREF(res); | |
| 7872 | 2340999 | return 0; | |
| 7873 | } | ||
| 7874 | |||
| 7875 | static PyObject *name_op[] = { | ||
| 7876 | &_Py_ID(__lt__), | ||
| 7877 | &_Py_ID(__le__), | ||
| 7878 | &_Py_ID(__eq__), | ||
| 7879 | &_Py_ID(__ne__), | ||
| 7880 | &_Py_ID(__gt__), | ||
| 7881 | &_Py_ID(__ge__), | ||
| 7882 | }; | ||
| 7883 | |||
| 7884 | static PyObject * | ||
| 7885 | 135410425 | slot_tp_richcompare(PyObject *self, PyObject *other, int op) | |
| 7886 | { | ||
| 7887 | 135410425 | PyThreadState *tstate = _PyThreadState_GET(); | |
| 7888 | |||
| 7889 | int unbound; | ||
| 7890 | 135410425 | PyObject *func = lookup_maybe_method(self, name_op[op], &unbound); | |
| 7891 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 135410425 times.
|
135410425 | if (func == NULL) { |
| 7892 | ✗ | PyErr_Clear(); | |
| 7893 | ✗ | Py_RETURN_NOTIMPLEMENTED; | |
| 7894 | } | ||
| 7895 | |||
| 7896 | 135410425 | PyObject *stack[2] = {self, other}; | |
| 7897 | 135410425 | PyObject *res = vectorcall_unbound(tstate, unbound, func, stack, 2); | |
| 7898 | 135410425 | Py_DECREF(func); | |
| 7899 | 135410425 | return res; | |
| 7900 | } | ||
| 7901 | |||
| 7902 | static PyObject * | ||
| 7903 | 9575075 | slot_tp_iter(PyObject *self) | |
| 7904 | { | ||
| 7905 | int unbound; | ||
| 7906 | PyObject *func, *res; | ||
| 7907 | |||
| 7908 | 9575075 | func = lookup_maybe_method(self, &_Py_ID(__iter__), &unbound); | |
| 7909 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 9575075 times.
|
9575075 | if (func == Py_None) { |
| 7910 | ✗ | Py_DECREF(func); | |
| 7911 | ✗ | PyErr_Format(PyExc_TypeError, | |
| 7912 | "'%.200s' object is not iterable", | ||
| 7913 | ✗ | Py_TYPE(self)->tp_name); | |
| 7914 | ✗ | return NULL; | |
| 7915 | } | ||
| 7916 | |||
| 7917 |
1/2✓ Branch 0 taken 9575075 times.
✗ Branch 1 not taken.
|
9575075 | if (func != NULL) { |
| 7918 | 9575075 | res = call_unbound_noarg(unbound, func, self); | |
| 7919 | 9575075 | Py_DECREF(func); | |
| 7920 | 9575075 | return res; | |
| 7921 | } | ||
| 7922 | |||
| 7923 | ✗ | PyErr_Clear(); | |
| 7924 | ✗ | func = lookup_maybe_method(self, &_Py_ID(__getitem__), &unbound); | |
| 7925 | ✗ | if (func == NULL) { | |
| 7926 | ✗ | PyErr_Format(PyExc_TypeError, | |
| 7927 | "'%.200s' object is not iterable", | ||
| 7928 | ✗ | Py_TYPE(self)->tp_name); | |
| 7929 | ✗ | return NULL; | |
| 7930 | } | ||
| 7931 | ✗ | Py_DECREF(func); | |
| 7932 | ✗ | return PySeqIter_New(self); | |
| 7933 | } | ||
| 7934 | |||
| 7935 | static PyObject * | ||
| 7936 | 20315091 | slot_tp_iternext(PyObject *self) | |
| 7937 | { | ||
| 7938 | 20315091 | PyObject *stack[1] = {self}; | |
| 7939 | 20315091 | return vectorcall_method(&_Py_ID(__next__), stack, 1); | |
| 7940 | } | ||
| 7941 | |||
| 7942 | static PyObject * | ||
| 7943 | 603014 | slot_tp_descr_get(PyObject *self, PyObject *obj, PyObject *type) | |
| 7944 | { | ||
| 7945 | 603014 | PyTypeObject *tp = Py_TYPE(self); | |
| 7946 | PyObject *get; | ||
| 7947 | |||
| 7948 | 603014 | get = _PyType_Lookup(tp, &_Py_ID(__get__)); | |
| 7949 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 603014 times.
|
603014 | if (get == NULL) { |
| 7950 | /* Avoid further slowdowns */ | ||
| 7951 | ✗ | if (tp->tp_descr_get == slot_tp_descr_get) | |
| 7952 | ✗ | tp->tp_descr_get = NULL; | |
| 7953 | ✗ | Py_INCREF(self); | |
| 7954 | ✗ | return self; | |
| 7955 | } | ||
| 7956 |
2/2✓ Branch 0 taken 82475 times.
✓ Branch 1 taken 520539 times.
|
603014 | if (obj == NULL) |
| 7957 | 82475 | obj = Py_None; | |
| 7958 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 603014 times.
|
603014 | if (type == NULL) |
| 7959 | ✗ | type = Py_None; | |
| 7960 | 603014 | return PyObject_CallFunctionObjArgs(get, self, obj, type, NULL); | |
| 7961 | } | ||
| 7962 | |||
| 7963 | static int | ||
| 7964 | 25244 | slot_tp_descr_set(PyObject *self, PyObject *target, PyObject *value) | |
| 7965 | { | ||
| 7966 | PyObject* stack[3]; | ||
| 7967 | PyObject *res; | ||
| 7968 | |||
| 7969 | 25244 | stack[0] = self; | |
| 7970 | 25244 | stack[1] = target; | |
| 7971 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 25244 times.
|
25244 | if (value == NULL) { |
| 7972 | ✗ | res = vectorcall_method(&_Py_ID(__delete__), stack, 2); | |
| 7973 | } | ||
| 7974 | else { | ||
| 7975 | 25244 | stack[2] = value; | |
| 7976 | 25244 | res = vectorcall_method(&_Py_ID(__set__), stack, 3); | |
| 7977 | } | ||
| 7978 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 25244 times.
|
25244 | if (res == NULL) |
| 7979 | ✗ | return -1; | |
| 7980 | 25244 | Py_DECREF(res); | |
| 7981 | 25244 | return 0; | |
| 7982 | } | ||
| 7983 | |||
| 7984 | static int | ||
| 7985 | 147937241 | slot_tp_init(PyObject *self, PyObject *args, PyObject *kwds) | |
| 7986 | { | ||
| 7987 | 147937241 | PyThreadState *tstate = _PyThreadState_GET(); | |
| 7988 | |||
| 7989 | int unbound; | ||
| 7990 | 147937241 | PyObject *meth = lookup_method(self, &_Py_ID(__init__), &unbound); | |
| 7991 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 147937241 times.
|
147937241 | if (meth == NULL) { |
| 7992 | ✗ | return -1; | |
| 7993 | } | ||
| 7994 | |||
| 7995 | PyObject *res; | ||
| 7996 |
1/2✓ Branch 0 taken 147937241 times.
✗ Branch 1 not taken.
|
147937241 | if (unbound) { |
| 7997 | 147937241 | res = _PyObject_Call_Prepend(tstate, meth, self, args, kwds); | |
| 7998 | } | ||
| 7999 | else { | ||
| 8000 | ✗ | res = _PyObject_Call(tstate, meth, args, kwds); | |
| 8001 | } | ||
| 8002 | 147937241 | Py_DECREF(meth); | |
| 8003 |
2/2✓ Branch 0 taken 169960 times.
✓ Branch 1 taken 147767281 times.
|
147937241 | if (res == NULL) |
| 8004 | 169960 | return -1; | |
| 8005 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 147767281 times.
|
147767281 | if (res != Py_None) { |
| 8006 | ✗ | PyErr_Format(PyExc_TypeError, | |
| 8007 | "__init__() should return None, not '%.200s'", | ||
| 8008 | ✗ | Py_TYPE(res)->tp_name); | |
| 8009 | ✗ | Py_DECREF(res); | |
| 8010 | ✗ | return -1; | |
| 8011 | } | ||
| 8012 | 147767281 | Py_DECREF(res); | |
| 8013 | 147767281 | return 0; | |
| 8014 | } | ||
| 8015 | |||
| 8016 | static PyObject * | ||
| 8017 | 60043234 | slot_tp_new(PyTypeObject *type, PyObject *args, PyObject *kwds) | |
| 8018 | { | ||
| 8019 | 60043234 | PyThreadState *tstate = _PyThreadState_GET(); | |
| 8020 | PyObject *func, *result; | ||
| 8021 | |||
| 8022 | 60043234 | func = PyObject_GetAttr((PyObject *)type, &_Py_ID(__new__)); | |
| 8023 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 60043234 times.
|
60043234 | if (func == NULL) { |
| 8024 | ✗ | return NULL; | |
| 8025 | } | ||
| 8026 | |||
| 8027 | 60043234 | result = _PyObject_Call_Prepend(tstate, func, (PyObject *)type, args, kwds); | |
| 8028 | 60043234 | Py_DECREF(func); | |
| 8029 | 60043234 | return result; | |
| 8030 | } | ||
| 8031 | |||
| 8032 | static void | ||
| 8033 | 8871 | slot_tp_finalize(PyObject *self) | |
| 8034 | { | ||
| 8035 | int unbound; | ||
| 8036 | PyObject *del, *res; | ||
| 8037 | PyObject *error_type, *error_value, *error_traceback; | ||
| 8038 | |||
| 8039 | /* Save the current exception, if any. */ | ||
| 8040 | 8871 | PyErr_Fetch(&error_type, &error_value, &error_traceback); | |
| 8041 | |||
| 8042 | /* Execute __del__ method, if any. */ | ||
| 8043 | 8871 | del = lookup_maybe_method(self, &_Py_ID(__del__), &unbound); | |
| 8044 |
1/2✓ Branch 0 taken 8871 times.
✗ Branch 1 not taken.
|
8871 | if (del != NULL) { |
| 8045 | 8871 | res = call_unbound_noarg(unbound, del, self); | |
| 8046 |
2/2✓ Branch 0 taken 131 times.
✓ Branch 1 taken 8740 times.
|
8871 | if (res == NULL) |
| 8047 | 131 | PyErr_WriteUnraisable(del); | |
| 8048 | else | ||
| 8049 | 8740 | Py_DECREF(res); | |
| 8050 | 8871 | Py_DECREF(del); | |
| 8051 | } | ||
| 8052 | |||
| 8053 | /* Restore the saved exception. */ | ||
| 8054 | 8871 | PyErr_Restore(error_type, error_value, error_traceback); | |
| 8055 | 8871 | } | |
| 8056 | |||
| 8057 | static PyObject * | ||
| 8058 | ✗ | slot_am_await(PyObject *self) | |
| 8059 | { | ||
| 8060 | int unbound; | ||
| 8061 | PyObject *func, *res; | ||
| 8062 | |||
| 8063 | ✗ | func = lookup_maybe_method(self, &_Py_ID(__await__), &unbound); | |
| 8064 | ✗ | if (func != NULL) { | |
| 8065 | ✗ | res = call_unbound_noarg(unbound, func, self); | |
| 8066 | ✗ | Py_DECREF(func); | |
| 8067 | ✗ | return res; | |
| 8068 | } | ||
| 8069 | ✗ | PyErr_Format(PyExc_AttributeError, | |
| 8070 | "object %.50s does not have __await__ method", | ||
| 8071 | ✗ | Py_TYPE(self)->tp_name); | |
| 8072 | ✗ | return NULL; | |
| 8073 | } | ||
| 8074 | |||
| 8075 | static PyObject * | ||
| 8076 | ✗ | slot_am_aiter(PyObject *self) | |
| 8077 | { | ||
| 8078 | int unbound; | ||
| 8079 | PyObject *func, *res; | ||
| 8080 | |||
| 8081 | ✗ | func = lookup_maybe_method(self, &_Py_ID(__aiter__), &unbound); | |
| 8082 | ✗ | if (func != NULL) { | |
| 8083 | ✗ | res = call_unbound_noarg(unbound, func, self); | |
| 8084 | ✗ | Py_DECREF(func); | |
| 8085 | ✗ | return res; | |
| 8086 | } | ||
| 8087 | ✗ | PyErr_Format(PyExc_AttributeError, | |
| 8088 | "object %.50s does not have __aiter__ method", | ||
| 8089 | ✗ | Py_TYPE(self)->tp_name); | |
| 8090 | ✗ | return NULL; | |
| 8091 | } | ||
| 8092 | |||
| 8093 | static PyObject * | ||
| 8094 | ✗ | slot_am_anext(PyObject *self) | |
| 8095 | { | ||
| 8096 | int unbound; | ||
| 8097 | PyObject *func, *res; | ||
| 8098 | |||
| 8099 | ✗ | func = lookup_maybe_method(self, &_Py_ID(__anext__), &unbound); | |
| 8100 | ✗ | if (func != NULL) { | |
| 8101 | ✗ | res = call_unbound_noarg(unbound, func, self); | |
| 8102 | ✗ | Py_DECREF(func); | |
| 8103 | ✗ | return res; | |
| 8104 | } | ||
| 8105 | ✗ | PyErr_Format(PyExc_AttributeError, | |
| 8106 | "object %.50s does not have __anext__ method", | ||
| 8107 | ✗ | Py_TYPE(self)->tp_name); | |
| 8108 | ✗ | return NULL; | |
| 8109 | } | ||
| 8110 | |||
| 8111 | /* | ||
| 8112 | Table mapping __foo__ names to tp_foo offsets and slot_tp_foo wrapper functions. | ||
| 8113 | |||
| 8114 | The table is ordered by offsets relative to the 'PyHeapTypeObject' structure, | ||
| 8115 | which incorporates the additional structures used for numbers, sequences and | ||
| 8116 | mappings. Note that multiple names may map to the same slot (e.g. __eq__, | ||
| 8117 | __ne__ etc. all map to tp_richcompare) and one name may map to multiple slots | ||
| 8118 | (e.g. __str__ affects tp_str as well as tp_repr). The table is terminated with | ||
| 8119 | an all-zero entry. (This table is further initialized in | ||
| 8120 | _PyTypes_InitSlotDefs().) | ||
| 8121 | */ | ||
| 8122 | |||
| 8123 | typedef struct wrapperbase slotdef; | ||
| 8124 | |||
| 8125 | #undef TPSLOT | ||
| 8126 | #undef FLSLOT | ||
| 8127 | #undef AMSLOT | ||
| 8128 | #undef ETSLOT | ||
| 8129 | #undef SQSLOT | ||
| 8130 | #undef MPSLOT | ||
| 8131 | #undef NBSLOT | ||
| 8132 | #undef UNSLOT | ||
| 8133 | #undef IBSLOT | ||
| 8134 | #undef BINSLOT | ||
| 8135 | #undef RBINSLOT | ||
| 8136 | |||
| 8137 | #define TPSLOT(NAME, SLOT, FUNCTION, WRAPPER, DOC) \ | ||
| 8138 | {NAME, offsetof(PyTypeObject, SLOT), (void *)(FUNCTION), WRAPPER, \ | ||
| 8139 | PyDoc_STR(DOC)} | ||
| 8140 | #define FLSLOT(NAME, SLOT, FUNCTION, WRAPPER, DOC, FLAGS) \ | ||
| 8141 | {NAME, offsetof(PyTypeObject, SLOT), (void *)(FUNCTION), WRAPPER, \ | ||
| 8142 | PyDoc_STR(DOC), FLAGS} | ||
| 8143 | #define ETSLOT(NAME, SLOT, FUNCTION, WRAPPER, DOC) \ | ||
| 8144 | {NAME, offsetof(PyHeapTypeObject, SLOT), (void *)(FUNCTION), WRAPPER, \ | ||
| 8145 | PyDoc_STR(DOC)} | ||
| 8146 | #define AMSLOT(NAME, SLOT, FUNCTION, WRAPPER, DOC) \ | ||
| 8147 | ETSLOT(NAME, as_async.SLOT, FUNCTION, WRAPPER, DOC) | ||
| 8148 | #define SQSLOT(NAME, SLOT, FUNCTION, WRAPPER, DOC) \ | ||
| 8149 | ETSLOT(NAME, as_sequence.SLOT, FUNCTION, WRAPPER, DOC) | ||
| 8150 | #define MPSLOT(NAME, SLOT, FUNCTION, WRAPPER, DOC) \ | ||
| 8151 | ETSLOT(NAME, as_mapping.SLOT, FUNCTION, WRAPPER, DOC) | ||
| 8152 | #define NBSLOT(NAME, SLOT, FUNCTION, WRAPPER, DOC) \ | ||
| 8153 | ETSLOT(NAME, as_number.SLOT, FUNCTION, WRAPPER, DOC) | ||
| 8154 | #define UNSLOT(NAME, SLOT, FUNCTION, WRAPPER, DOC) \ | ||
| 8155 | ETSLOT(NAME, as_number.SLOT, FUNCTION, WRAPPER, \ | ||
| 8156 | NAME "($self, /)\n--\n\n" DOC) | ||
| 8157 | #define IBSLOT(NAME, SLOT, FUNCTION, WRAPPER, DOC) \ | ||
| 8158 | ETSLOT(NAME, as_number.SLOT, FUNCTION, WRAPPER, \ | ||
| 8159 | NAME "($self, value, /)\n--\n\nReturn self" DOC "value.") | ||
| 8160 | #define BINSLOT(NAME, SLOT, FUNCTION, DOC) \ | ||
| 8161 | ETSLOT(NAME, as_number.SLOT, FUNCTION, wrap_binaryfunc_l, \ | ||
| 8162 | NAME "($self, value, /)\n--\n\nReturn self" DOC "value.") | ||
| 8163 | #define RBINSLOT(NAME, SLOT, FUNCTION, DOC) \ | ||
| 8164 | ETSLOT(NAME, as_number.SLOT, FUNCTION, wrap_binaryfunc_r, \ | ||
| 8165 | NAME "($self, value, /)\n--\n\nReturn value" DOC "self.") | ||
| 8166 | #define BINSLOTNOTINFIX(NAME, SLOT, FUNCTION, DOC) \ | ||
| 8167 | ETSLOT(NAME, as_number.SLOT, FUNCTION, wrap_binaryfunc_l, \ | ||
| 8168 | NAME "($self, value, /)\n--\n\n" DOC) | ||
| 8169 | #define RBINSLOTNOTINFIX(NAME, SLOT, FUNCTION, DOC) \ | ||
| 8170 | ETSLOT(NAME, as_number.SLOT, FUNCTION, wrap_binaryfunc_r, \ | ||
| 8171 | NAME "($self, value, /)\n--\n\n" DOC) | ||
| 8172 | |||
| 8173 | static slotdef slotdefs[] = { | ||
| 8174 | TPSLOT("__getattribute__", tp_getattr, NULL, NULL, ""), | ||
| 8175 | TPSLOT("__getattr__", tp_getattr, NULL, NULL, ""), | ||
| 8176 | TPSLOT("__setattr__", tp_setattr, NULL, NULL, ""), | ||
| 8177 | TPSLOT("__delattr__", tp_setattr, NULL, NULL, ""), | ||
| 8178 | TPSLOT("__repr__", tp_repr, slot_tp_repr, wrap_unaryfunc, | ||
| 8179 | "__repr__($self, /)\n--\n\nReturn repr(self)."), | ||
| 8180 | TPSLOT("__hash__", tp_hash, slot_tp_hash, wrap_hashfunc, | ||
| 8181 | "__hash__($self, /)\n--\n\nReturn hash(self)."), | ||
| 8182 | FLSLOT("__call__", tp_call, slot_tp_call, (wrapperfunc)(void(*)(void))wrap_call, | ||
| 8183 | "__call__($self, /, *args, **kwargs)\n--\n\nCall self as a function.", | ||
| 8184 | PyWrapperFlag_KEYWORDS), | ||
| 8185 | TPSLOT("__str__", tp_str, slot_tp_str, wrap_unaryfunc, | ||
| 8186 | "__str__($self, /)\n--\n\nReturn str(self)."), | ||
| 8187 | TPSLOT("__getattribute__", tp_getattro, slot_tp_getattr_hook, | ||
| 8188 | wrap_binaryfunc, | ||
| 8189 | "__getattribute__($self, name, /)\n--\n\nReturn getattr(self, name)."), | ||
| 8190 | TPSLOT("__getattr__", tp_getattro, slot_tp_getattr_hook, NULL, ""), | ||
| 8191 | TPSLOT("__setattr__", tp_setattro, slot_tp_setattro, wrap_setattr, | ||
| 8192 | "__setattr__($self, name, value, /)\n--\n\nImplement setattr(self, name, value)."), | ||
| 8193 | TPSLOT("__delattr__", tp_setattro, slot_tp_setattro, wrap_delattr, | ||
| 8194 | "__delattr__($self, name, /)\n--\n\nImplement delattr(self, name)."), | ||
| 8195 | TPSLOT("__lt__", tp_richcompare, slot_tp_richcompare, richcmp_lt, | ||
| 8196 | "__lt__($self, value, /)\n--\n\nReturn self<value."), | ||
| 8197 | TPSLOT("__le__", tp_richcompare, slot_tp_richcompare, richcmp_le, | ||
| 8198 | "__le__($self, value, /)\n--\n\nReturn self<=value."), | ||
| 8199 | TPSLOT("__eq__", tp_richcompare, slot_tp_richcompare, richcmp_eq, | ||
| 8200 | "__eq__($self, value, /)\n--\n\nReturn self==value."), | ||
| 8201 | TPSLOT("__ne__", tp_richcompare, slot_tp_richcompare, richcmp_ne, | ||
| 8202 | "__ne__($self, value, /)\n--\n\nReturn self!=value."), | ||
| 8203 | TPSLOT("__gt__", tp_richcompare, slot_tp_richcompare, richcmp_gt, | ||
| 8204 | "__gt__($self, value, /)\n--\n\nReturn self>value."), | ||
| 8205 | TPSLOT("__ge__", tp_richcompare, slot_tp_richcompare, richcmp_ge, | ||
| 8206 | "__ge__($self, value, /)\n--\n\nReturn self>=value."), | ||
| 8207 | TPSLOT("__iter__", tp_iter, slot_tp_iter, wrap_unaryfunc, | ||
| 8208 | "__iter__($self, /)\n--\n\nImplement iter(self)."), | ||
| 8209 | TPSLOT("__next__", tp_iternext, slot_tp_iternext, wrap_next, | ||
| 8210 | "__next__($self, /)\n--\n\nImplement next(self)."), | ||
| 8211 | TPSLOT("__get__", tp_descr_get, slot_tp_descr_get, wrap_descr_get, | ||
| 8212 | "__get__($self, instance, owner=None, /)\n--\n\nReturn an attribute of instance, which is of type owner."), | ||
| 8213 | TPSLOT("__set__", tp_descr_set, slot_tp_descr_set, wrap_descr_set, | ||
| 8214 | "__set__($self, instance, value, /)\n--\n\nSet an attribute of instance to value."), | ||
| 8215 | TPSLOT("__delete__", tp_descr_set, slot_tp_descr_set, | ||
| 8216 | wrap_descr_delete, | ||
| 8217 | "__delete__($self, instance, /)\n--\n\nDelete an attribute of instance."), | ||
| 8218 | FLSLOT("__init__", tp_init, slot_tp_init, (wrapperfunc)(void(*)(void))wrap_init, | ||
| 8219 | "__init__($self, /, *args, **kwargs)\n--\n\n" | ||
| 8220 | "Initialize self. See help(type(self)) for accurate signature.", | ||
| 8221 | PyWrapperFlag_KEYWORDS), | ||
| 8222 | TPSLOT("__new__", tp_new, slot_tp_new, NULL, | ||
| 8223 | "__new__(type, /, *args, **kwargs)\n--\n\n" | ||
| 8224 | "Create and return new object. See help(type) for accurate signature."), | ||
| 8225 | TPSLOT("__del__", tp_finalize, slot_tp_finalize, (wrapperfunc)wrap_del, ""), | ||
| 8226 | |||
| 8227 | AMSLOT("__await__", am_await, slot_am_await, wrap_unaryfunc, | ||
| 8228 | "__await__($self, /)\n--\n\nReturn an iterator to be used in await expression."), | ||
| 8229 | AMSLOT("__aiter__", am_aiter, slot_am_aiter, wrap_unaryfunc, | ||
| 8230 | "__aiter__($self, /)\n--\n\nReturn an awaitable, that resolves in asynchronous iterator."), | ||
| 8231 | AMSLOT("__anext__", am_anext, slot_am_anext, wrap_unaryfunc, | ||
| 8232 | "__anext__($self, /)\n--\n\nReturn a value or raise StopAsyncIteration."), | ||
| 8233 | |||
| 8234 | BINSLOT("__add__", nb_add, slot_nb_add, | ||
| 8235 | "+"), | ||
| 8236 | RBINSLOT("__radd__", nb_add, slot_nb_add, | ||
| 8237 | "+"), | ||
| 8238 | BINSLOT("__sub__", nb_subtract, slot_nb_subtract, | ||
| 8239 | "-"), | ||
| 8240 | RBINSLOT("__rsub__", nb_subtract, slot_nb_subtract, | ||
| 8241 | "-"), | ||
| 8242 | BINSLOT("__mul__", nb_multiply, slot_nb_multiply, | ||
| 8243 | "*"), | ||
| 8244 | RBINSLOT("__rmul__", nb_multiply, slot_nb_multiply, | ||
| 8245 | "*"), | ||
| 8246 | BINSLOT("__mod__", nb_remainder, slot_nb_remainder, | ||
| 8247 | "%"), | ||
| 8248 | RBINSLOT("__rmod__", nb_remainder, slot_nb_remainder, | ||
| 8249 | "%"), | ||
| 8250 | BINSLOTNOTINFIX("__divmod__", nb_divmod, slot_nb_divmod, | ||
| 8251 | "Return divmod(self, value)."), | ||
| 8252 | RBINSLOTNOTINFIX("__rdivmod__", nb_divmod, slot_nb_divmod, | ||
| 8253 | "Return divmod(value, self)."), | ||
| 8254 | NBSLOT("__pow__", nb_power, slot_nb_power, wrap_ternaryfunc, | ||
| 8255 | "__pow__($self, value, mod=None, /)\n--\n\nReturn pow(self, value, mod)."), | ||
| 8256 | NBSLOT("__rpow__", nb_power, slot_nb_power, wrap_ternaryfunc_r, | ||
| 8257 | "__rpow__($self, value, mod=None, /)\n--\n\nReturn pow(value, self, mod)."), | ||
| 8258 | UNSLOT("__neg__", nb_negative, slot_nb_negative, wrap_unaryfunc, "-self"), | ||
| 8259 | UNSLOT("__pos__", nb_positive, slot_nb_positive, wrap_unaryfunc, "+self"), | ||
| 8260 | UNSLOT("__abs__", nb_absolute, slot_nb_absolute, wrap_unaryfunc, | ||
| 8261 | "abs(self)"), | ||
| 8262 | UNSLOT("__bool__", nb_bool, slot_nb_bool, wrap_inquirypred, | ||
| 8263 | "True if self else False"), | ||
| 8264 | UNSLOT("__invert__", nb_invert, slot_nb_invert, wrap_unaryfunc, "~self"), | ||
| 8265 | BINSLOT("__lshift__", nb_lshift, slot_nb_lshift, "<<"), | ||
| 8266 | RBINSLOT("__rlshift__", nb_lshift, slot_nb_lshift, "<<"), | ||
| 8267 | BINSLOT("__rshift__", nb_rshift, slot_nb_rshift, ">>"), | ||
| 8268 | RBINSLOT("__rrshift__", nb_rshift, slot_nb_rshift, ">>"), | ||
| 8269 | BINSLOT("__and__", nb_and, slot_nb_and, "&"), | ||
| 8270 | RBINSLOT("__rand__", nb_and, slot_nb_and, "&"), | ||
| 8271 | BINSLOT("__xor__", nb_xor, slot_nb_xor, "^"), | ||
| 8272 | RBINSLOT("__rxor__", nb_xor, slot_nb_xor, "^"), | ||
| 8273 | BINSLOT("__or__", nb_or, slot_nb_or, "|"), | ||
| 8274 | RBINSLOT("__ror__", nb_or, slot_nb_or, "|"), | ||
| 8275 | UNSLOT("__int__", nb_int, slot_nb_int, wrap_unaryfunc, | ||
| 8276 | "int(self)"), | ||
| 8277 | UNSLOT("__float__", nb_float, slot_nb_float, wrap_unaryfunc, | ||
| 8278 | "float(self)"), | ||
| 8279 | IBSLOT("__iadd__", nb_inplace_add, slot_nb_inplace_add, | ||
| 8280 | wrap_binaryfunc, "+="), | ||
| 8281 | IBSLOT("__isub__", nb_inplace_subtract, slot_nb_inplace_subtract, | ||
| 8282 | wrap_binaryfunc, "-="), | ||
| 8283 | IBSLOT("__imul__", nb_inplace_multiply, slot_nb_inplace_multiply, | ||
| 8284 | wrap_binaryfunc, "*="), | ||
| 8285 | IBSLOT("__imod__", nb_inplace_remainder, slot_nb_inplace_remainder, | ||
| 8286 | wrap_binaryfunc, "%="), | ||
| 8287 | IBSLOT("__ipow__", nb_inplace_power, slot_nb_inplace_power, | ||
| 8288 | wrap_ternaryfunc, "**="), | ||
| 8289 | IBSLOT("__ilshift__", nb_inplace_lshift, slot_nb_inplace_lshift, | ||
| 8290 | wrap_binaryfunc, "<<="), | ||
| 8291 | IBSLOT("__irshift__", nb_inplace_rshift, slot_nb_inplace_rshift, | ||
| 8292 | wrap_binaryfunc, ">>="), | ||
| 8293 | IBSLOT("__iand__", nb_inplace_and, slot_nb_inplace_and, | ||
| 8294 | wrap_binaryfunc, "&="), | ||
| 8295 | IBSLOT("__ixor__", nb_inplace_xor, slot_nb_inplace_xor, | ||
| 8296 | wrap_binaryfunc, "^="), | ||
| 8297 | IBSLOT("__ior__", nb_inplace_or, slot_nb_inplace_or, | ||
| 8298 | wrap_binaryfunc, "|="), | ||
| 8299 | BINSLOT("__floordiv__", nb_floor_divide, slot_nb_floor_divide, "//"), | ||
| 8300 | RBINSLOT("__rfloordiv__", nb_floor_divide, slot_nb_floor_divide, "//"), | ||
| 8301 | BINSLOT("__truediv__", nb_true_divide, slot_nb_true_divide, "/"), | ||
| 8302 | RBINSLOT("__rtruediv__", nb_true_divide, slot_nb_true_divide, "/"), | ||
| 8303 | IBSLOT("__ifloordiv__", nb_inplace_floor_divide, | ||
| 8304 | slot_nb_inplace_floor_divide, wrap_binaryfunc, "//="), | ||
| 8305 | IBSLOT("__itruediv__", nb_inplace_true_divide, | ||
| 8306 | slot_nb_inplace_true_divide, wrap_binaryfunc, "/="), | ||
| 8307 | NBSLOT("__index__", nb_index, slot_nb_index, wrap_unaryfunc, | ||
| 8308 | "__index__($self, /)\n--\n\n" | ||
| 8309 | "Return self converted to an integer, if self is suitable " | ||
| 8310 | "for use as an index into a list."), | ||
| 8311 | BINSLOT("__matmul__", nb_matrix_multiply, slot_nb_matrix_multiply, | ||
| 8312 | "@"), | ||
| 8313 | RBINSLOT("__rmatmul__", nb_matrix_multiply, slot_nb_matrix_multiply, | ||
| 8314 | "@"), | ||
| 8315 | IBSLOT("__imatmul__", nb_inplace_matrix_multiply, slot_nb_inplace_matrix_multiply, | ||
| 8316 | wrap_binaryfunc, "@="), | ||
| 8317 | MPSLOT("__len__", mp_length, slot_mp_length, wrap_lenfunc, | ||
| 8318 | "__len__($self, /)\n--\n\nReturn len(self)."), | ||
| 8319 | MPSLOT("__getitem__", mp_subscript, slot_mp_subscript, | ||
| 8320 | wrap_binaryfunc, | ||
| 8321 | "__getitem__($self, key, /)\n--\n\nReturn self[key]."), | ||
| 8322 | MPSLOT("__setitem__", mp_ass_subscript, slot_mp_ass_subscript, | ||
| 8323 | wrap_objobjargproc, | ||
| 8324 | "__setitem__($self, key, value, /)\n--\n\nSet self[key] to value."), | ||
| 8325 | MPSLOT("__delitem__", mp_ass_subscript, slot_mp_ass_subscript, | ||
| 8326 | wrap_delitem, | ||
| 8327 | "__delitem__($self, key, /)\n--\n\nDelete self[key]."), | ||
| 8328 | |||
| 8329 | SQSLOT("__len__", sq_length, slot_sq_length, wrap_lenfunc, | ||
| 8330 | "__len__($self, /)\n--\n\nReturn len(self)."), | ||
| 8331 | /* Heap types defining __add__/__mul__ have sq_concat/sq_repeat == NULL. | ||
| 8332 | The logic in abstract.c always falls back to nb_add/nb_multiply in | ||
| 8333 | this case. Defining both the nb_* and the sq_* slots to call the | ||
| 8334 | user-defined methods has unexpected side-effects, as shown by | ||
| 8335 | test_descr.notimplemented() */ | ||
| 8336 | SQSLOT("__add__", sq_concat, NULL, wrap_binaryfunc, | ||
| 8337 | "__add__($self, value, /)\n--\n\nReturn self+value."), | ||
| 8338 | SQSLOT("__mul__", sq_repeat, NULL, wrap_indexargfunc, | ||
| 8339 | "__mul__($self, value, /)\n--\n\nReturn self*value."), | ||
| 8340 | SQSLOT("__rmul__", sq_repeat, NULL, wrap_indexargfunc, | ||
| 8341 | "__rmul__($self, value, /)\n--\n\nReturn value*self."), | ||
| 8342 | SQSLOT("__getitem__", sq_item, slot_sq_item, wrap_sq_item, | ||
| 8343 | "__getitem__($self, key, /)\n--\n\nReturn self[key]."), | ||
| 8344 | SQSLOT("__setitem__", sq_ass_item, slot_sq_ass_item, wrap_sq_setitem, | ||
| 8345 | "__setitem__($self, key, value, /)\n--\n\nSet self[key] to value."), | ||
| 8346 | SQSLOT("__delitem__", sq_ass_item, slot_sq_ass_item, wrap_sq_delitem, | ||
| 8347 | "__delitem__($self, key, /)\n--\n\nDelete self[key]."), | ||
| 8348 | SQSLOT("__contains__", sq_contains, slot_sq_contains, wrap_objobjproc, | ||
| 8349 | "__contains__($self, key, /)\n--\n\nReturn key in self."), | ||
| 8350 | SQSLOT("__iadd__", sq_inplace_concat, NULL, | ||
| 8351 | wrap_binaryfunc, | ||
| 8352 | "__iadd__($self, value, /)\n--\n\nImplement self+=value."), | ||
| 8353 | SQSLOT("__imul__", sq_inplace_repeat, NULL, | ||
| 8354 | wrap_indexargfunc, | ||
| 8355 | "__imul__($self, value, /)\n--\n\nImplement self*=value."), | ||
| 8356 | |||
| 8357 | {NULL} | ||
| 8358 | }; | ||
| 8359 | |||
| 8360 | /* Given a type pointer and an offset gotten from a slotdef entry, return a | ||
| 8361 | pointer to the actual slot. This is not quite the same as simply adding | ||
| 8362 | the offset to the type pointer, since it takes care to indirect through the | ||
| 8363 | proper indirection pointer (as_buffer, etc.); it returns NULL if the | ||
| 8364 | indirection pointer is NULL. */ | ||
| 8365 | static void ** | ||
| 8366 | 355243320 | slotptr(PyTypeObject *type, int ioffset) | |
| 8367 | { | ||
| 8368 | char *ptr; | ||
| 8369 | 355243320 | long offset = ioffset; | |
| 8370 | |||
| 8371 | /* Note: this depends on the order of the members of PyHeapTypeObject! */ | ||
| 8372 | assert(offset >= 0); | ||
| 8373 | assert((size_t)offset < offsetof(PyHeapTypeObject, as_buffer)); | ||
| 8374 |
2/2✓ Branch 0 taken 39483581 times.
✓ Branch 1 taken 315759739 times.
|
355243320 | if ((size_t)offset >= offsetof(PyHeapTypeObject, as_sequence)) { |
| 8375 | 39483581 | ptr = (char *)type->tp_as_sequence; | |
| 8376 | 39483581 | offset -= offsetof(PyHeapTypeObject, as_sequence); | |
| 8377 | } | ||
| 8378 |
2/2✓ Branch 0 taken 15349633 times.
✓ Branch 1 taken 300410106 times.
|
315759739 | else if ((size_t)offset >= offsetof(PyHeapTypeObject, as_mapping)) { |
| 8379 | 15349633 | ptr = (char *)type->tp_as_mapping; | |
| 8380 | 15349633 | offset -= offsetof(PyHeapTypeObject, as_mapping); | |
| 8381 | } | ||
| 8382 |
2/2✓ Branch 0 taken 179799610 times.
✓ Branch 1 taken 120610496 times.
|
300410106 | else if ((size_t)offset >= offsetof(PyHeapTypeObject, as_number)) { |
| 8383 | 179799610 | ptr = (char *)type->tp_as_number; | |
| 8384 | 179799610 | offset -= offsetof(PyHeapTypeObject, as_number); | |
| 8385 | } | ||
| 8386 |
2/2✓ Branch 0 taken 12216618 times.
✓ Branch 1 taken 108393878 times.
|
120610496 | else if ((size_t)offset >= offsetof(PyHeapTypeObject, as_async)) { |
| 8387 | 12216618 | ptr = (char *)type->tp_as_async; | |
| 8388 | 12216618 | offset -= offsetof(PyHeapTypeObject, as_async); | |
| 8389 | } | ||
| 8390 | else { | ||
| 8391 | 108393878 | ptr = (char *)type; | |
| 8392 | } | ||
| 8393 |
2/2✓ Branch 0 taken 309506019 times.
✓ Branch 1 taken 45737301 times.
|
355243320 | if (ptr != NULL) |
| 8394 | 309506019 | ptr += offset; | |
| 8395 | 355243320 | return (void **)ptr; | |
| 8396 | } | ||
| 8397 | |||
| 8398 | /* Length of array of slotdef pointers used to store slots with the | ||
| 8399 | same __name__. There should be at most MAX_EQUIV-1 slotdef entries with | ||
| 8400 | the same __name__, for any __name__. Since that's a static property, it is | ||
| 8401 | appropriate to declare fixed-size arrays for this. */ | ||
| 8402 | #define MAX_EQUIV 10 | ||
| 8403 | |||
| 8404 | /* Return a slot pointer for a given name, but ONLY if the attribute has | ||
| 8405 | exactly one slot function. The name must be an interned string. */ | ||
| 8406 | static void ** | ||
| 8407 | 26597878 | resolve_slotdups(PyTypeObject *type, PyObject *name) | |
| 8408 | { | ||
| 8409 | /* XXX Maybe this could be optimized more -- but is it worth it? */ | ||
| 8410 | |||
| 8411 | /* pname and ptrs act as a little cache */ | ||
| 8412 | static PyObject *pname; | ||
| 8413 | static slotdef *ptrs[MAX_EQUIV]; | ||
| 8414 | slotdef *p, **pp; | ||
| 8415 | void **res, **ptr; | ||
| 8416 | |||
| 8417 |
2/2✓ Branch 0 taken 26533329 times.
✓ Branch 1 taken 64549 times.
|
26597878 | if (pname != name) { |
| 8418 | /* Collect all slotdefs that match name into ptrs. */ | ||
| 8419 | 26533329 | pname = name; | |
| 8420 | 26533329 | pp = ptrs; | |
| 8421 |
2/2✓ Branch 0 taken 2441066268 times.
✓ Branch 1 taken 26533329 times.
|
2467599597 | for (p = slotdefs; p->name_strobj; p++) { |
| 8422 |
2/2✓ Branch 0 taken 37789737 times.
✓ Branch 1 taken 2403276531 times.
|
2441066268 | if (p->name_strobj == name) |
| 8423 | 37789737 | *pp++ = p; | |
| 8424 | } | ||
| 8425 | 26533329 | *pp = NULL; | |
| 8426 | } | ||
| 8427 | |||
| 8428 | /* Look in all slots of the type matching the name. If exactly one of these | ||
| 8429 | has a filled-in slot, return a pointer to that slot. | ||
| 8430 | Otherwise, return NULL. */ | ||
| 8431 | 26597878 | res = NULL; | |
| 8432 |
2/2✓ Branch 0 taken 37918747 times.
✓ Branch 1 taken 26016854 times.
|
63935601 | for (pp = ptrs; *pp; pp++) { |
| 8433 | 37918747 | ptr = slotptr(type, (*pp)->offset); | |
| 8434 |
3/4✓ Branch 0 taken 37918747 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11128155 times.
✓ Branch 3 taken 26790592 times.
|
37918747 | if (ptr == NULL || *ptr == NULL) |
| 8435 | 11128155 | continue; | |
| 8436 |
2/2✓ Branch 0 taken 581024 times.
✓ Branch 1 taken 26209568 times.
|
26790592 | if (res != NULL) |
| 8437 | 581024 | return NULL; | |
| 8438 | 26209568 | res = ptr; | |
| 8439 | } | ||
| 8440 | 26016854 | return res; | |
| 8441 | } | ||
| 8442 | |||
| 8443 | |||
| 8444 | /* Common code for update_slots_callback() and fixup_slot_dispatchers(). | ||
| 8445 | * | ||
| 8446 | * This is meant to set a "slot" like type->tp_repr or | ||
| 8447 | * type->tp_as_sequence->sq_concat by looking up special methods like | ||
| 8448 | * __repr__ or __add__. The opposite (adding special methods from slots) is | ||
| 8449 | * done by add_operators(), called from PyType_Ready(). Since update_one_slot() | ||
| 8450 | * calls PyType_Ready() if needed, the special methods are already in place. | ||
| 8451 | * | ||
| 8452 | * The special methods corresponding to each slot are defined in the "slotdef" | ||
| 8453 | * array. Note that one slot may correspond to multiple special methods and vice | ||
| 8454 | * versa. For example, tp_richcompare uses 6 methods __lt__, ..., __ge__ and | ||
| 8455 | * tp_as_number->nb_add uses __add__ and __radd__. In the other direction, | ||
| 8456 | * __add__ is used by the number and sequence protocols and __getitem__ by the | ||
| 8457 | * sequence and mapping protocols. This causes a lot of complications. | ||
| 8458 | * | ||
| 8459 | * In detail, update_one_slot() does the following: | ||
| 8460 | * | ||
| 8461 | * First of all, if the slot in question does not exist, return immediately. | ||
| 8462 | * This can happen for example if it's tp_as_number->nb_add but tp_as_number | ||
| 8463 | * is NULL. | ||
| 8464 | * | ||
| 8465 | * For the given slot, we loop over all the special methods with a name | ||
| 8466 | * corresponding to that slot (for example, for tp_descr_set, this would be | ||
| 8467 | * __set__ and __delete__) and we look up these names in the MRO of the type. | ||
| 8468 | * If we don't find any special method, the slot is set to NULL (regardless of | ||
| 8469 | * what was in the slot before). | ||
| 8470 | * | ||
| 8471 | * Suppose that we find exactly one special method. If it's a wrapper_descriptor | ||
| 8472 | * (i.e. a special method calling a slot, for example str.__repr__ which calls | ||
| 8473 | * the tp_repr for the 'str' class) with the correct name ("__repr__" for | ||
| 8474 | * tp_repr), for the right class, calling the right wrapper C function (like | ||
| 8475 | * wrap_unaryfunc for tp_repr), then the slot is set to the slot that the | ||
| 8476 | * wrapper_descriptor originally wrapped. For example, a class inheriting | ||
| 8477 | * from 'str' and not redefining __repr__ will have tp_repr set to the tp_repr | ||
| 8478 | * of 'str'. | ||
| 8479 | * In all other cases where the special method exists, the slot is set to a | ||
| 8480 | * wrapper calling the special method. There is one exception: if the special | ||
| 8481 | * method is a wrapper_descriptor with the correct name but the type has | ||
| 8482 | * precisely one slot set for that name and that slot is not the one that we | ||
| 8483 | * are updating, then NULL is put in the slot (this exception is the only place | ||
| 8484 | * in update_one_slot() where the *existing* slots matter). | ||
| 8485 | * | ||
| 8486 | * When there are multiple special methods for the same slot, the above is | ||
| 8487 | * applied for each special method. As long as the results agree, the common | ||
| 8488 | * resulting slot is applied. If the results disagree, then a wrapper for | ||
| 8489 | * the special methods is installed. This is always safe, but less efficient | ||
| 8490 | * because it uses method lookup instead of direct C calls. | ||
| 8491 | * | ||
| 8492 | * There are some further special cases for specific slots, like supporting | ||
| 8493 | * __hash__ = None for tp_hash and special code for tp_new. | ||
| 8494 | * | ||
| 8495 | * When done, return a pointer to the next slotdef with a different offset, | ||
| 8496 | * because that's convenient for fixup_slot_dispatchers(). This function never | ||
| 8497 | * sets an exception: if an internal error happens (unlikely), it's ignored. */ | ||
| 8498 | static slotdef * | ||
| 8499 | 103642437 | update_one_slot(PyTypeObject *type, slotdef *p) | |
| 8500 | { | ||
| 8501 | PyObject *descr; | ||
| 8502 | PyWrapperDescrObject *d; | ||
| 8503 | 103642437 | void *generic = NULL, *specific = NULL; | |
| 8504 | 103642437 | int use_generic = 0; | |
| 8505 | 103642437 | int offset = p->offset; | |
| 8506 | int error; | ||
| 8507 | 103642437 | void **ptr = slotptr(type, offset); | |
| 8508 | |||
| 8509 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 103642437 times.
|
103642437 | if (ptr == NULL) { |
| 8510 | do { | ||
| 8511 | ✗ | ++p; | |
| 8512 | ✗ | } while (p->offset == offset); | |
| 8513 | ✗ | return p; | |
| 8514 | } | ||
| 8515 | /* We may end up clearing live exceptions below, so make sure it's ours. */ | ||
| 8516 | assert(!PyErr_Occurred()); | ||
| 8517 | do { | ||
| 8518 | /* Use faster uncached lookup as we won't get any cache hits during type setup. */ | ||
| 8519 | 146899708 | descr = find_name_in_mro(type, p->name_strobj, &error); | |
| 8520 |
2/2✓ Branch 0 taken 112719416 times.
✓ Branch 1 taken 34180292 times.
|
146899708 | if (descr == NULL) { |
| 8521 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 112719416 times.
|
112719416 | if (error == -1) { |
| 8522 | /* It is unlikely but not impossible that there has been an exception | ||
| 8523 | during lookup. Since this function originally expected no errors, | ||
| 8524 | we ignore them here in order to keep up the interface. */ | ||
| 8525 | ✗ | PyErr_Clear(); | |
| 8526 | } | ||
| 8527 |
2/2✓ Branch 0 taken 1530937 times.
✓ Branch 1 taken 111188479 times.
|
112719416 | if (ptr == (void**)&type->tp_iternext) { |
| 8528 | 1530937 | specific = (void *)_PyObject_NextNotImplemented; | |
| 8529 | } | ||
| 8530 | 112719416 | continue; | |
| 8531 | } | ||
| 8532 |
2/2✓ Branch 1 taken 26658720 times.
✓ Branch 2 taken 7521572 times.
|
34180292 | if (Py_IS_TYPE(descr, &PyWrapperDescr_Type) && |
| 8533 |
2/2✓ Branch 0 taken 26597878 times.
✓ Branch 1 taken 60842 times.
|
53256598 | ((PyWrapperDescrObject *)descr)->d_base->name_strobj == p->name_strobj) { |
| 8534 | 26597878 | void **tptr = resolve_slotdups(type, p->name_strobj); | |
| 8535 |
4/4✓ Branch 0 taken 25628544 times.
✓ Branch 1 taken 969334 times.
✓ Branch 2 taken 20252891 times.
✓ Branch 3 taken 5375653 times.
|
26597878 | if (tptr == NULL || tptr == ptr) |
| 8536 | 21222225 | generic = p->function; | |
| 8537 | 26597878 | d = (PyWrapperDescrObject *)descr; | |
| 8538 |
4/4✓ Branch 0 taken 9786459 times.
✓ Branch 1 taken 16811419 times.
✓ Branch 2 taken 9783725 times.
✓ Branch 3 taken 2734 times.
|
26597878 | if ((specific == NULL || specific == d->d_wrapped) && |
| 8539 |
3/4✓ Branch 0 taken 21089525 times.
✓ Branch 1 taken 5505619 times.
✓ Branch 2 taken 21089525 times.
✗ Branch 3 not taken.
|
47684669 | d->d_base->wrapper == p->wrapper && |
| 8540 | 21089525 | PyType_IsSubtype(type, PyDescr_TYPE(d))) | |
| 8541 | { | ||
| 8542 | 21089525 | specific = d->d_wrapped; | |
| 8543 | } | ||
| 8544 | else { | ||
| 8545 | /* We cannot use the specific slot function because either | ||
| 8546 | - it is not unique: there are multiple methods for this | ||
| 8547 | slot and they conflict | ||
| 8548 | - the signature is wrong (as checked by the ->wrapper | ||
| 8549 | comparison above) | ||
| 8550 | - it's wrapping the wrong class | ||
| 8551 | */ | ||
| 8552 | 5508353 | use_generic = 1; | |
| 8553 | } | ||
| 8554 | } | ||
| 8555 |
4/4✓ Branch 1 taken 1333382 times.
✓ Branch 2 taken 6249032 times.
✓ Branch 3 taken 1332720 times.
✓ Branch 4 taken 662 times.
|
8915796 | else if (Py_IS_TYPE(descr, &PyCFunction_Type) && |
| 8556 | 1333382 | PyCFunction_GET_FUNCTION(descr) == | |
| 8557 | 1332720 | _PyCFunction_CAST(tp_new_wrapper) && | |
| 8558 |
1/2✓ Branch 0 taken 1332720 times.
✗ Branch 1 not taken.
|
1332720 | ptr == (void**)&type->tp_new) |
| 8559 | { | ||
| 8560 | /* The __new__ wrapper is not a wrapper descriptor, | ||
| 8561 | so must be special-cased differently. | ||
| 8562 | If we don't do this, creating an instance will | ||
| 8563 | always use slot_tp_new which will look up | ||
| 8564 | __new__ in the MRO which will call tp_new_wrapper | ||
| 8565 | which will look through the base classes looking | ||
| 8566 | for a static base and call its tp_new (usually | ||
| 8567 | PyType_GenericNew), after performing various | ||
| 8568 | sanity checks and constructing a new argument | ||
| 8569 | list. Cut all that nonsense short -- this speeds | ||
| 8570 | up instance creation tremendously. */ | ||
| 8571 | 1332720 | specific = (void *)type->tp_new; | |
| 8572 | /* XXX I'm not 100% sure that there isn't a hole | ||
| 8573 | in this reasoning that requires additional | ||
| 8574 | sanity checks. I'll buy the first person to | ||
| 8575 | point out a bug in this reasoning a beer. */ | ||
| 8576 | } | ||
| 8577 |
2/2✓ Branch 0 taken 119188 times.
✓ Branch 1 taken 6130506 times.
|
6249694 | else if (descr == Py_None && |
| 8578 |
2/2✓ Branch 0 taken 98010 times.
✓ Branch 1 taken 21178 times.
|
119188 | ptr == (void**)&type->tp_hash) { |
| 8579 | /* We specifically allow __hash__ to be set to None | ||
| 8580 | to prevent inheritance of the default | ||
| 8581 | implementation from object.__hash__ */ | ||
| 8582 | 98010 | specific = (void *)PyObject_HashNotImplemented; | |
| 8583 | } | ||
| 8584 | else { | ||
| 8585 | 6151684 | use_generic = 1; | |
| 8586 | 6151684 | generic = p->function; | |
| 8587 | } | ||
| 8588 |
2/2✓ Branch 0 taken 43257271 times.
✓ Branch 1 taken 103642437 times.
|
146899708 | } while ((++p)->offset == offset); |
| 8589 |
4/4✓ Branch 0 taken 14267467 times.
✓ Branch 1 taken 89374970 times.
✓ Branch 2 taken 13998257 times.
✓ Branch 3 taken 269210 times.
|
103642437 | if (specific && !use_generic) |
| 8590 | 13998257 | *ptr = specific; | |
| 8591 | else | ||
| 8592 | 89644180 | *ptr = generic; | |
| 8593 | 103642437 | return p; | |
| 8594 | } | ||
| 8595 | |||
| 8596 | /* In the type, update the slots whose slotdefs are gathered in the pp array. | ||
| 8597 | This is a callback for update_subclasses(). */ | ||
| 8598 | static int | ||
| 8599 | 639204 | update_slots_callback(PyTypeObject *type, void *data) | |
| 8600 | { | ||
| 8601 | 639204 | slotdef **pp = (slotdef **)data; | |
| 8602 |
2/2✓ Branch 0 taken 763492 times.
✓ Branch 1 taken 639204 times.
|
1402696 | for (; *pp; pp++) { |
| 8603 | 763492 | update_one_slot(type, *pp); | |
| 8604 | } | ||
| 8605 | 639204 | return 0; | |
| 8606 | } | ||
| 8607 | |||
| 8608 | static int slotdefs_initialized = 0; | ||
| 8609 | /* Initialize the slotdefs table by adding interned string objects for the | ||
| 8610 | names. */ | ||
| 8611 | PyStatus | ||
| 8612 | 3408 | _PyTypes_InitSlotDefs(void) | |
| 8613 | { | ||
| 8614 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3408 times.
|
3408 | if (slotdefs_initialized) { |
| 8615 | ✗ | return _PyStatus_OK(); | |
| 8616 | } | ||
| 8617 | |||
| 8618 |
2/2✓ Branch 0 taken 313536 times.
✓ Branch 1 taken 3408 times.
|
316944 | for (slotdef *p = slotdefs; p->name; p++) { |
| 8619 | /* Slots must be ordered by their offset in the PyHeapTypeObject. */ | ||
| 8620 | assert(!p[1].name || p->offset <= p[1].offset); | ||
| 8621 | /* bpo-40521: Interned strings are shared by all subinterpreters */ | ||
| 8622 | 313536 | p->name_strobj = PyUnicode_InternFromString(p->name); | |
| 8623 |
2/4✓ Branch 0 taken 313536 times.
✗ Branch 1 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 313536 times.
|
313536 | if (!p->name_strobj || !PyUnicode_CHECK_INTERNED(p->name_strobj)) { |
| 8624 | ✗ | return _PyStatus_NO_MEMORY(); | |
| 8625 | } | ||
| 8626 | } | ||
| 8627 | 3408 | slotdefs_initialized = 1; | |
| 8628 | 3408 | return _PyStatus_OK(); | |
| 8629 | } | ||
| 8630 | |||
| 8631 | /* Undo _PyTypes_InitSlotDefs(), releasing the interned strings. */ | ||
| 8632 | 3404 | static void clear_slotdefs(void) | |
| 8633 | { | ||
| 8634 |
2/2✓ Branch 0 taken 313168 times.
✓ Branch 1 taken 3404 times.
|
316572 | for (slotdef *p = slotdefs; p->name; p++) { |
| 8635 |
1/2✓ Branch 0 taken 313168 times.
✗ Branch 1 not taken.
|
313168 | Py_CLEAR(p->name_strobj); |
| 8636 | } | ||
| 8637 | 3404 | slotdefs_initialized = 0; | |
| 8638 | 3404 | } | |
| 8639 | |||
| 8640 | /* Update the slots after assignment to a class (type) attribute. */ | ||
| 8641 | static int | ||
| 8642 | 1213017 | update_slot(PyTypeObject *type, PyObject *name) | |
| 8643 | { | ||
| 8644 | slotdef *ptrs[MAX_EQUIV]; | ||
| 8645 | slotdef *p; | ||
| 8646 | slotdef **pp; | ||
| 8647 | int offset; | ||
| 8648 | |||
| 8649 | assert(PyUnicode_CheckExact(name)); | ||
| 8650 | assert(PyUnicode_CHECK_INTERNED(name)); | ||
| 8651 | |||
| 8652 | assert(slotdefs_initialized); | ||
| 8653 | 1213017 | pp = ptrs; | |
| 8654 |
2/2✓ Branch 0 taken 111597564 times.
✓ Branch 1 taken 1213017 times.
|
112810581 | for (p = slotdefs; p->name; p++) { |
| 8655 | assert(PyUnicode_CheckExact(p->name_strobj)); | ||
| 8656 | assert(PyUnicode_CheckExact(name)); | ||
| 8657 | /* bpo-40521: Using interned strings. */ | ||
| 8658 |
2/2✓ Branch 0 taken 763492 times.
✓ Branch 1 taken 110834072 times.
|
111597564 | if (p->name_strobj == name) { |
| 8659 | 763492 | *pp++ = p; | |
| 8660 | } | ||
| 8661 | } | ||
| 8662 | 1213017 | *pp = NULL; | |
| 8663 |
2/2✓ Branch 0 taken 763492 times.
✓ Branch 1 taken 1213017 times.
|
1976509 | for (pp = ptrs; *pp; pp++) { |
| 8664 | 763492 | p = *pp; | |
| 8665 | 763492 | offset = p->offset; | |
| 8666 |
4/4✓ Branch 0 taken 1005625 times.
✓ Branch 1 taken 18620 times.
✓ Branch 2 taken 260753 times.
✓ Branch 3 taken 744872 times.
|
1024245 | while (p > slotdefs && (p-1)->offset == offset) |
| 8667 | 260753 | --p; | |
| 8668 | 763492 | *pp = p; | |
| 8669 | } | ||
| 8670 |
2/2✓ Branch 0 taken 573813 times.
✓ Branch 1 taken 639204 times.
|
1213017 | if (ptrs[0] == NULL) |
| 8671 | 573813 | return 0; /* Not an attribute that affects any slots */ | |
| 8672 | 639204 | return update_subclasses(type, name, | |
| 8673 | update_slots_callback, (void *)ptrs); | ||
| 8674 | } | ||
| 8675 | |||
| 8676 | /* Store the proper functions in the slot dispatches at class (type) | ||
| 8677 | definition time, based upon which operations the class overrides in its | ||
| 8678 | dict. */ | ||
| 8679 | static void | ||
| 8680 | 1582753 | fixup_slot_dispatchers(PyTypeObject *type) | |
| 8681 | { | ||
| 8682 | assert(!PyErr_Occurred()); | ||
| 8683 | assert(slotdefs_initialized); | ||
| 8684 |
2/2✓ Branch 0 taken 102878945 times.
✓ Branch 1 taken 1582753 times.
|
104461698 | for (slotdef *p = slotdefs; p->name; ) { |
| 8685 | 102878945 | p = update_one_slot(type, p); | |
| 8686 | } | ||
| 8687 | 1582753 | } | |
| 8688 | |||
| 8689 | static void | ||
| 8690 | 4655 | update_all_slots(PyTypeObject* type) | |
| 8691 | { | ||
| 8692 | slotdef *p; | ||
| 8693 | |||
| 8694 | /* Clear the VALID_VERSION flag of 'type' and all its subclasses. */ | ||
| 8695 | 4655 | PyType_Modified(type); | |
| 8696 | |||
| 8697 | assert(slotdefs_initialized); | ||
| 8698 |
2/2✓ Branch 0 taken 428260 times.
✓ Branch 1 taken 4655 times.
|
432915 | for (p = slotdefs; p->name; p++) { |
| 8699 | /* update_slot returns int but can't actually fail */ | ||
| 8700 | 428260 | update_slot(type, p->name_strobj); | |
| 8701 | } | ||
| 8702 | 4655 | } | |
| 8703 | |||
| 8704 | |||
| 8705 | /* Call __set_name__ on all attributes (including descriptors) | ||
| 8706 | in a newly generated type */ | ||
| 8707 | static int | ||
| 8708 | 1582753 | type_new_set_names(PyTypeObject *type) | |
| 8709 | { | ||
| 8710 | 1582753 | PyObject *names_to_set = PyDict_Copy(type->tp_dict); | |
| 8711 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1582753 times.
|
1582753 | if (names_to_set == NULL) { |
| 8712 | ✗ | return -1; | |
| 8713 | } | ||
| 8714 | |||
| 8715 | 1582753 | Py_ssize_t i = 0; | |
| 8716 | PyObject *key, *value; | ||
| 8717 |
2/2✓ Branch 1 taken 15880883 times.
✓ Branch 2 taken 1582753 times.
|
17463636 | while (PyDict_Next(names_to_set, &i, &key, &value)) { |
| 8718 | 15880883 | PyObject *set_name = _PyObject_LookupSpecial(value, | |
| 8719 | &_Py_ID(__set_name__)); | ||
| 8720 |
2/2✓ Branch 0 taken 15345074 times.
✓ Branch 1 taken 535809 times.
|
15880883 | if (set_name == NULL) { |
| 8721 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 15345074 times.
|
15345074 | if (PyErr_Occurred()) { |
| 8722 | ✗ | goto error; | |
| 8723 | } | ||
| 8724 | 15345074 | continue; | |
| 8725 | } | ||
| 8726 | |||
| 8727 | 535809 | PyObject *res = PyObject_CallFunctionObjArgs(set_name, type, key, NULL); | |
| 8728 | 535809 | Py_DECREF(set_name); | |
| 8729 | |||
| 8730 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 535809 times.
|
535809 | if (res == NULL) { |
| 8731 | ✗ | _PyErr_FormatFromCause(PyExc_RuntimeError, | |
| 8732 | "Error calling __set_name__ on '%.100s' instance %R " | ||
| 8733 | "in '%.100s'", | ||
| 8734 | ✗ | Py_TYPE(value)->tp_name, key, type->tp_name); | |
| 8735 | ✗ | goto error; | |
| 8736 | } | ||
| 8737 | 535809 | Py_DECREF(res); | |
| 8738 | } | ||
| 8739 | |||
| 8740 | 1582753 | Py_DECREF(names_to_set); | |
| 8741 | 1582753 | return 0; | |
| 8742 | |||
| 8743 | ✗ | error: | |
| 8744 | ✗ | Py_DECREF(names_to_set); | |
| 8745 | ✗ | return -1; | |
| 8746 | } | ||
| 8747 | |||
| 8748 | |||
| 8749 | /* Call __init_subclass__ on the parent of a newly generated type */ | ||
| 8750 | static int | ||
| 8751 | 1582753 | type_new_init_subclass(PyTypeObject *type, PyObject *kwds) | |
| 8752 | { | ||
| 8753 | 1582753 | PyObject *args[2] = {(PyObject *)type, (PyObject *)type}; | |
| 8754 | 1582753 | PyObject *super = _PyObject_FastCall((PyObject *)&PySuper_Type, args, 2); | |
| 8755 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1582753 times.
|
1582753 | if (super == NULL) { |
| 8756 | ✗ | return -1; | |
| 8757 | } | ||
| 8758 | |||
| 8759 | 1582753 | PyObject *func = PyObject_GetAttr(super, &_Py_ID(__init_subclass__)); | |
| 8760 | 1582753 | Py_DECREF(super); | |
| 8761 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1582753 times.
|
1582753 | if (func == NULL) { |
| 8762 | ✗ | return -1; | |
| 8763 | } | ||
| 8764 | |||
| 8765 | 1582753 | PyObject *result = PyObject_VectorcallDict(func, NULL, 0, kwds); | |
| 8766 | 1582753 | Py_DECREF(func); | |
| 8767 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1582753 times.
|
1582753 | if (result == NULL) { |
| 8768 | ✗ | return -1; | |
| 8769 | } | ||
| 8770 | |||
| 8771 | 1582753 | Py_DECREF(result); | |
| 8772 | 1582753 | return 0; | |
| 8773 | } | ||
| 8774 | |||
| 8775 | |||
| 8776 | /* recurse_down_subclasses() and update_subclasses() are mutually | ||
| 8777 | recursive functions to call a callback for all subclasses, | ||
| 8778 | but refraining from recursing into subclasses that define 'attr_name'. */ | ||
| 8779 | |||
| 8780 | static int | ||
| 8781 | 639204 | update_subclasses(PyTypeObject *type, PyObject *attr_name, | |
| 8782 | update_callback callback, void *data) | ||
| 8783 | { | ||
| 8784 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 639204 times.
|
639204 | if (callback(type, data) < 0) { |
| 8785 | ✗ | return -1; | |
| 8786 | } | ||
| 8787 | 639204 | return recurse_down_subclasses(type, attr_name, callback, data); | |
| 8788 | } | ||
| 8789 | |||
| 8790 | static int | ||
| 8791 | 639204 | recurse_down_subclasses(PyTypeObject *type, PyObject *attr_name, | |
| 8792 | update_callback callback, void *data) | ||
| 8793 | { | ||
| 8794 | // It is safe to use a borrowed reference because update_subclasses() is | ||
| 8795 | // only used with update_slots_callback() which doesn't modify | ||
| 8796 | // tp_subclasses. | ||
| 8797 | 639204 | PyObject *subclasses = type->tp_subclasses; // borrowed ref | |
| 8798 |
1/2✓ Branch 0 taken 639204 times.
✗ Branch 1 not taken.
|
639204 | if (subclasses == NULL) { |
| 8799 | 639204 | return 0; | |
| 8800 | } | ||
| 8801 | assert(PyDict_CheckExact(subclasses)); | ||
| 8802 | |||
| 8803 | ✗ | Py_ssize_t i = 0; | |
| 8804 | PyObject *ref; | ||
| 8805 | ✗ | while (PyDict_Next(subclasses, &i, NULL, &ref)) { | |
| 8806 | assert(PyWeakref_CheckRef(ref)); | ||
| 8807 | ✗ | PyObject *obj = PyWeakref_GET_OBJECT(ref); | |
| 8808 | assert(obj != NULL); | ||
| 8809 | ✗ | if (obj == Py_None) { | |
| 8810 | ✗ | continue; | |
| 8811 | } | ||
| 8812 | ✗ | PyTypeObject *subclass = _PyType_CAST(obj); | |
| 8813 | |||
| 8814 | /* Avoid recursing down into unaffected classes */ | ||
| 8815 | ✗ | PyObject *dict = subclass->tp_dict; | |
| 8816 | ✗ | if (dict != NULL && PyDict_Check(dict)) { | |
| 8817 | ✗ | int r = PyDict_Contains(dict, attr_name); | |
| 8818 | ✗ | if (r < 0) { | |
| 8819 | ✗ | return -1; | |
| 8820 | } | ||
| 8821 | ✗ | if (r > 0) { | |
| 8822 | ✗ | continue; | |
| 8823 | } | ||
| 8824 | } | ||
| 8825 | |||
| 8826 | ✗ | if (update_subclasses(subclass, attr_name, callback, data) < 0) { | |
| 8827 | ✗ | return -1; | |
| 8828 | } | ||
| 8829 | } | ||
| 8830 | ✗ | return 0; | |
| 8831 | } | ||
| 8832 | |||
| 8833 | /* This function is called by PyType_Ready() to populate the type's | ||
| 8834 | dictionary with method descriptors for function slots. For each | ||
| 8835 | function slot (like tp_repr) that's defined in the type, one or more | ||
| 8836 | corresponding descriptors are added in the type's tp_dict dictionary | ||
| 8837 | under the appropriate name (like __repr__). Some function slots | ||
| 8838 | cause more than one descriptor to be added (for example, the nb_add | ||
| 8839 | slot adds both __add__ and __radd__ descriptors) and some function | ||
| 8840 | slots compete for the same descriptor (for example both sq_item and | ||
| 8841 | mp_subscript generate a __getitem__ descriptor). | ||
| 8842 | |||
| 8843 | In the latter case, the first slotdef entry encountered wins. Since | ||
| 8844 | slotdef entries are sorted by the offset of the slot in the | ||
| 8845 | PyHeapTypeObject, this gives us some control over disambiguating | ||
| 8846 | between competing slots: the members of PyHeapTypeObject are listed | ||
| 8847 | from most general to least general, so the most general slot is | ||
| 8848 | preferred. In particular, because as_mapping comes before as_sequence, | ||
| 8849 | for a type that defines both mp_subscript and sq_item, mp_subscript | ||
| 8850 | wins. | ||
| 8851 | |||
| 8852 | This only adds new descriptors and doesn't overwrite entries in | ||
| 8853 | tp_dict that were previously defined. The descriptors contain a | ||
| 8854 | reference to the C function they must call, so that it's safe if they | ||
| 8855 | are copied into a subtype's __dict__ and the subtype has a different | ||
| 8856 | C function in its slot -- calling the method defined by the | ||
| 8857 | descriptor will call the C function that was used to create it, | ||
| 8858 | rather than the C function present in the slot when it is called. | ||
| 8859 | (This is important because a subtype may have a C function in the | ||
| 8860 | slot that calls the method from the dictionary, and we want to avoid | ||
| 8861 | infinite recursion here.) */ | ||
| 8862 | |||
| 8863 | static int | ||
| 8864 | 2484676 | add_operators(PyTypeObject *type) | |
| 8865 | { | ||
| 8866 | 2484676 | PyObject *dict = type->tp_dict; | |
| 8867 | slotdef *p; | ||
| 8868 | PyObject *descr; | ||
| 8869 | void **ptr; | ||
| 8870 | |||
| 8871 | assert(slotdefs_initialized); | ||
| 8872 |
2/2✓ Branch 0 taken 228590192 times.
✓ Branch 1 taken 2484676 times.
|
231074868 | for (p = slotdefs; p->name; p++) { |
| 8873 |
2/2✓ Branch 0 taken 14908056 times.
✓ Branch 1 taken 213682136 times.
|
228590192 | if (p->wrapper == NULL) |
| 8874 | 14908056 | continue; | |
| 8875 | 213682136 | ptr = slotptr(type, p->offset); | |
| 8876 |
4/4✓ Branch 0 taken 167944835 times.
✓ Branch 1 taken 45737301 times.
✓ Branch 2 taken 163738589 times.
✓ Branch 3 taken 4206246 times.
|
213682136 | if (!ptr || !*ptr) |
| 8877 | 209475890 | continue; | |
| 8878 | 4206246 | int r = PyDict_Contains(dict, p->name_strobj); | |
| 8879 |
2/2✓ Branch 0 taken 78732 times.
✓ Branch 1 taken 4127514 times.
|
4206246 | if (r > 0) |
| 8880 | 78732 | continue; | |
| 8881 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4127514 times.
|
4127514 | if (r < 0) { |
| 8882 | ✗ | return -1; | |
| 8883 | } | ||
| 8884 |
2/2✓ Branch 0 taken 39476 times.
✓ Branch 1 taken 4088038 times.
|
4127514 | if (*ptr == (void *)PyObject_HashNotImplemented) { |
| 8885 | /* Classes may prevent the inheritance of the tp_hash | ||
| 8886 | slot by storing PyObject_HashNotImplemented in it. Make it | ||
| 8887 | visible as a None value for the __hash__ attribute. */ | ||
| 8888 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 39476 times.
|
39476 | if (PyDict_SetItem(dict, p->name_strobj, Py_None) < 0) |
| 8889 | ✗ | return -1; | |
| 8890 | } | ||
| 8891 | else { | ||
| 8892 | 4088038 | descr = PyDescr_NewWrapper(type, p, *ptr); | |
| 8893 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4088038 times.
|
4088038 | if (descr == NULL) |
| 8894 | ✗ | return -1; | |
| 8895 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 4088038 times.
|
4088038 | if (PyDict_SetItem(dict, p->name_strobj, descr) < 0) { |
| 8896 | ✗ | Py_DECREF(descr); | |
| 8897 | ✗ | return -1; | |
| 8898 | } | ||
| 8899 | 4088038 | Py_DECREF(descr); | |
| 8900 | } | ||
| 8901 | } | ||
| 8902 | 2484676 | return 0; | |
| 8903 | } | ||
| 8904 | |||
| 8905 | |||
| 8906 | /* Cooperative 'super' */ | ||
| 8907 | |||
| 8908 | typedef struct { | ||
| 8909 | PyObject_HEAD | ||
| 8910 | PyTypeObject *type; | ||
| 8911 | PyObject *obj; | ||
| 8912 | PyTypeObject *obj_type; | ||
| 8913 | } superobject; | ||
| 8914 | |||
| 8915 | static PyMemberDef super_members[] = { | ||
| 8916 | {"__thisclass__", T_OBJECT, offsetof(superobject, type), READONLY, | ||
| 8917 | "the class invoking super()"}, | ||
| 8918 | {"__self__", T_OBJECT, offsetof(superobject, obj), READONLY, | ||
| 8919 | "the instance invoking super(); may be None"}, | ||
| 8920 | {"__self_class__", T_OBJECT, offsetof(superobject, obj_type), READONLY, | ||
| 8921 | "the type of the instance invoking super(); may be None"}, | ||
| 8922 | {0} | ||
| 8923 | }; | ||
| 8924 | |||
| 8925 | static void | ||
| 8926 | 63082538 | super_dealloc(PyObject *self) | |
| 8927 | { | ||
| 8928 | 63082538 | superobject *su = (superobject *)self; | |
| 8929 | |||
| 8930 | 63082538 | _PyObject_GC_UNTRACK(self); | |
| 8931 | 63082538 | Py_XDECREF(su->obj); | |
| 8932 | 63082538 | Py_XDECREF(su->type); | |
| 8933 | 63082538 | Py_XDECREF(su->obj_type); | |
| 8934 | 63082538 | Py_TYPE(self)->tp_free(self); | |
| 8935 | 63082538 | } | |
| 8936 | |||
| 8937 | static PyObject * | ||
| 8938 | ✗ | super_repr(PyObject *self) | |
| 8939 | { | ||
| 8940 | ✗ | superobject *su = (superobject *)self; | |
| 8941 | |||
| 8942 | ✗ | if (su->obj_type) | |
| 8943 | ✗ | return PyUnicode_FromFormat( | |
| 8944 | "<super: <class '%s'>, <%s object>>", | ||
| 8945 | ✗ | su->type ? su->type->tp_name : "NULL", | |
| 8946 | ✗ | su->obj_type->tp_name); | |
| 8947 | else | ||
| 8948 | ✗ | return PyUnicode_FromFormat( | |
| 8949 | "<super: <class '%s'>, NULL>", | ||
| 8950 | ✗ | su->type ? su->type->tp_name : "NULL"); | |
| 8951 | } | ||
| 8952 | |||
| 8953 | static PyObject * | ||
| 8954 | 63083108 | super_getattro(PyObject *self, PyObject *name) | |
| 8955 | { | ||
| 8956 | 63083108 | superobject *su = (superobject *)self; | |
| 8957 | PyTypeObject *starttype; | ||
| 8958 | PyObject *mro; | ||
| 8959 | Py_ssize_t i, n; | ||
| 8960 | |||
| 8961 | 63083108 | starttype = su->obj_type; | |
| 8962 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 63083108 times.
|
63083108 | if (starttype == NULL) |
| 8963 | ✗ | goto skip; | |
| 8964 | |||
| 8965 | /* We want __class__ to return the class of the super object | ||
| 8966 | (i.e. super, or a subclass), not the class of su->obj. */ | ||
| 8967 |
3/4✓ Branch 2 taken 63083108 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 285654 times.
✓ Branch 5 taken 62797454 times.
|
126166216 | if (PyUnicode_Check(name) && |
| 8968 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 285654 times.
|
63368762 | PyUnicode_GET_LENGTH(name) == 9 && |
| 8969 | 285654 | _PyUnicode_Equal(name, &_Py_ID(__class__))) | |
| 8970 | ✗ | goto skip; | |
| 8971 | |||
| 8972 | 63083108 | mro = starttype->tp_mro; | |
| 8973 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 63083108 times.
|
63083108 | if (mro == NULL) |
| 8974 | ✗ | goto skip; | |
| 8975 | |||
| 8976 | assert(PyTuple_Check(mro)); | ||
| 8977 | 63083108 | n = PyTuple_GET_SIZE(mro); | |
| 8978 | |||
| 8979 | /* No need to check the last one: it's gonna be skipped anyway. */ | ||
| 8980 |
1/2✓ Branch 0 taken 69900721 times.
✗ Branch 1 not taken.
|
69900721 | for (i = 0; i+1 < n; i++) { |
| 8981 |
2/2✓ Branch 0 taken 63083108 times.
✓ Branch 1 taken 6817613 times.
|
69900721 | if ((PyObject *)(su->type) == PyTuple_GET_ITEM(mro, i)) |
| 8982 | 63083108 | break; | |
| 8983 | } | ||
| 8984 | 63083108 | i++; /* skip su->type (if any) */ | |
| 8985 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 63083108 times.
|
63083108 | if (i >= n) |
| 8986 | ✗ | goto skip; | |
| 8987 | |||
| 8988 | /* keep a strong reference to mro because starttype->tp_mro can be | ||
| 8989 | replaced during PyDict_GetItemWithError(dict, name) */ | ||
| 8990 | 63083108 | Py_INCREF(mro); | |
| 8991 | do { | ||
| 8992 | 233925837 | PyObject *obj = PyTuple_GET_ITEM(mro, i); | |
| 8993 | 233925837 | PyObject *dict = _PyType_CAST(obj)->tp_dict; | |
| 8994 | assert(dict != NULL && PyDict_Check(dict)); | ||
| 8995 | |||
| 8996 | 233925837 | PyObject *res = PyDict_GetItemWithError(dict, name); | |
| 8997 |
2/2✓ Branch 0 taken 63083094 times.
✓ Branch 1 taken 170842743 times.
|
233925837 | if (res != NULL) { |
| 8998 | 63083094 | Py_INCREF(res); | |
| 8999 | |||
| 9000 | 63083094 | descrgetfunc f = Py_TYPE(res)->tp_descr_get; | |
| 9001 |
2/2✓ Branch 0 taken 21458511 times.
✓ Branch 1 taken 41624583 times.
|
63083094 | if (f != NULL) { |
| 9002 | PyObject *res2; | ||
| 9003 | 21458511 | res2 = f(res, | |
| 9004 | /* Only pass 'obj' param if this is instance-mode super | ||
| 9005 | (See SF ID #743627) */ | ||
| 9006 |
2/2✓ Branch 0 taken 18564138 times.
✓ Branch 1 taken 2894373 times.
|
21458511 | (su->obj == (PyObject *)starttype) ? NULL : su->obj, |
| 9007 | (PyObject *)starttype); | ||
| 9008 | 21458511 | Py_DECREF(res); | |
| 9009 | 21458511 | res = res2; | |
| 9010 | } | ||
| 9011 | |||
| 9012 | 63083094 | Py_DECREF(mro); | |
| 9013 | 63083094 | return res; | |
| 9014 | } | ||
| 9015 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 170842743 times.
|
170842743 | else if (PyErr_Occurred()) { |
| 9016 | ✗ | Py_DECREF(mro); | |
| 9017 | ✗ | return NULL; | |
| 9018 | } | ||
| 9019 | |||
| 9020 | 170842743 | i++; | |
| 9021 |
2/2✓ Branch 0 taken 170842729 times.
✓ Branch 1 taken 14 times.
|
170842743 | } while (i < n); |
| 9022 | 14 | Py_DECREF(mro); | |
| 9023 | |||
| 9024 | 14 | skip: | |
| 9025 | 14 | return PyObject_GenericGetAttr(self, name); | |
| 9026 | } | ||
| 9027 | |||
| 9028 | static PyTypeObject * | ||
| 9029 | 63082538 | supercheck(PyTypeObject *type, PyObject *obj) | |
| 9030 | { | ||
| 9031 | /* Check that a super() call makes sense. Return a type object. | ||
| 9032 | |||
| 9033 | obj can be a class, or an instance of one: | ||
| 9034 | |||
| 9035 | - If it is a class, it must be a subclass of 'type'. This case is | ||
| 9036 | used for class methods; the return value is obj. | ||
| 9037 | |||
| 9038 | - If it is an instance, it must be an instance of 'type'. This is | ||
| 9039 | the normal case; the return value is obj.__class__. | ||
| 9040 | |||
| 9041 | But... when obj is an instance, we want to allow for the case where | ||
| 9042 | Py_TYPE(obj) is not a subclass of type, but obj.__class__ is! | ||
| 9043 | This will allow using super() with a proxy for obj. | ||
| 9044 | */ | ||
| 9045 | |||
| 9046 | /* Check for first bullet above (special case) */ | ||
| 9047 |
4/4✓ Branch 1 taken 45522736 times.
✓ Branch 2 taken 17559802 times.
✓ Branch 4 taken 44518956 times.
✓ Branch 5 taken 1003780 times.
|
63082538 | if (PyType_Check(obj) && PyType_IsSubtype((PyTypeObject *)obj, type)) { |
| 9048 | 44518956 | Py_INCREF(obj); | |
| 9049 | 44518956 | return (PyTypeObject *)obj; | |
| 9050 | } | ||
| 9051 | |||
| 9052 | /* Normal case */ | ||
| 9053 |
1/2✓ Branch 2 taken 18563582 times.
✗ Branch 3 not taken.
|
18563582 | if (PyType_IsSubtype(Py_TYPE(obj), type)) { |
| 9054 | 18563582 | Py_INCREF(Py_TYPE(obj)); | |
| 9055 | 18563582 | return Py_TYPE(obj); | |
| 9056 | } | ||
| 9057 | else { | ||
| 9058 | /* Try the slow way */ | ||
| 9059 | PyObject *class_attr; | ||
| 9060 | |||
| 9061 | ✗ | if (_PyObject_LookupAttr(obj, &_Py_ID(__class__), &class_attr) < 0) { | |
| 9062 | ✗ | return NULL; | |
| 9063 | } | ||
| 9064 | ✗ | if (class_attr != NULL && | |
| 9065 | ✗ | PyType_Check(class_attr) && | |
| 9066 | ✗ | (PyTypeObject *)class_attr != Py_TYPE(obj)) | |
| 9067 | { | ||
| 9068 | ✗ | int ok = PyType_IsSubtype( | |
| 9069 | (PyTypeObject *)class_attr, type); | ||
| 9070 | ✗ | if (ok) { | |
| 9071 | ✗ | return (PyTypeObject *)class_attr; | |
| 9072 | } | ||
| 9073 | } | ||
| 9074 | ✗ | Py_XDECREF(class_attr); | |
| 9075 | } | ||
| 9076 | |||
| 9077 | ✗ | PyErr_SetString(PyExc_TypeError, | |
| 9078 | "super(type, obj): " | ||
| 9079 | "obj must be an instance or subtype of type"); | ||
| 9080 | ✗ | return NULL; | |
| 9081 | } | ||
| 9082 | |||
| 9083 | static PyObject * | ||
| 9084 | ✗ | super_descr_get(PyObject *self, PyObject *obj, PyObject *type) | |
| 9085 | { | ||
| 9086 | ✗ | superobject *su = (superobject *)self; | |
| 9087 | superobject *newobj; | ||
| 9088 | |||
| 9089 | ✗ | if (obj == NULL || obj == Py_None || su->obj != NULL) { | |
| 9090 | /* Not binding to an object, or already bound */ | ||
| 9091 | ✗ | Py_INCREF(self); | |
| 9092 | ✗ | return self; | |
| 9093 | } | ||
| 9094 | ✗ | if (!Py_IS_TYPE(su, &PySuper_Type)) | |
| 9095 | /* If su is an instance of a (strict) subclass of super, | ||
| 9096 | call its type */ | ||
| 9097 | ✗ | return PyObject_CallFunctionObjArgs((PyObject *)Py_TYPE(su), | |
| 9098 | su->type, obj, NULL); | ||
| 9099 | else { | ||
| 9100 | /* Inline the common case */ | ||
| 9101 | ✗ | PyTypeObject *obj_type = supercheck(su->type, obj); | |
| 9102 | ✗ | if (obj_type == NULL) | |
| 9103 | ✗ | return NULL; | |
| 9104 | ✗ | newobj = (superobject *)PySuper_Type.tp_new(&PySuper_Type, | |
| 9105 | NULL, NULL); | ||
| 9106 | ✗ | if (newobj == NULL) | |
| 9107 | ✗ | return NULL; | |
| 9108 | ✗ | Py_INCREF(su->type); | |
| 9109 | ✗ | Py_INCREF(obj); | |
| 9110 | ✗ | newobj->type = su->type; | |
| 9111 | ✗ | newobj->obj = obj; | |
| 9112 | ✗ | newobj->obj_type = obj_type; | |
| 9113 | ✗ | return (PyObject *)newobj; | |
| 9114 | } | ||
| 9115 | } | ||
| 9116 | |||
| 9117 | static int | ||
| 9118 | 19436364 | super_init_without_args(_PyInterpreterFrame *cframe, PyCodeObject *co, | |
| 9119 | PyTypeObject **type_p, PyObject **obj_p) | ||
| 9120 | { | ||
| 9121 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 19436364 times.
|
19436364 | if (co->co_argcount == 0) { |
| 9122 | ✗ | PyErr_SetString(PyExc_RuntimeError, | |
| 9123 | "super(): no arguments"); | ||
| 9124 | ✗ | return -1; | |
| 9125 | } | ||
| 9126 | |||
| 9127 | assert(cframe->f_code->co_nlocalsplus > 0); | ||
| 9128 | 19436364 | PyObject *firstarg = _PyFrame_GetLocalsArray(cframe)[0]; | |
| 9129 | // The first argument might be a cell. | ||
| 9130 |
3/4✓ Branch 0 taken 19436364 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 137494 times.
✓ Branch 4 taken 19298870 times.
|
19436364 | if (firstarg != NULL && (_PyLocals_GetKind(co->co_localspluskinds, 0) & CO_FAST_CELL)) { |
| 9131 | // "firstarg" is a cell here unless (very unlikely) super() | ||
| 9132 | // was called from the C-API before the first MAKE_CELL op. | ||
| 9133 |
1/2✓ Branch 0 taken 137494 times.
✗ Branch 1 not taken.
|
137494 | if (_PyInterpreterFrame_LASTI(cframe) >= 0) { |
| 9134 | // MAKE_CELL and COPY_FREE_VARS have no quickened forms, so no need | ||
| 9135 | // to use _PyOpcode_Deopt here: | ||
| 9136 | assert(_Py_OPCODE(_PyCode_CODE(co)[0]) == MAKE_CELL || | ||
| 9137 | _Py_OPCODE(_PyCode_CODE(co)[0]) == COPY_FREE_VARS); | ||
| 9138 | assert(PyCell_Check(firstarg)); | ||
| 9139 | 137494 | firstarg = PyCell_GET(firstarg); | |
| 9140 | } | ||
| 9141 | } | ||
| 9142 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 19436364 times.
|
19436364 | if (firstarg == NULL) { |
| 9143 | ✗ | PyErr_SetString(PyExc_RuntimeError, | |
| 9144 | "super(): arg[0] deleted"); | ||
| 9145 | ✗ | return -1; | |
| 9146 | } | ||
| 9147 | |||
| 9148 | // Look for __class__ in the free vars. | ||
| 9149 | 19436364 | PyTypeObject *type = NULL; | |
| 9150 | 19436364 | int i = co->co_nlocals + co->co_nplaincellvars; | |
| 9151 |
1/2✓ Branch 0 taken 19436364 times.
✗ Branch 1 not taken.
|
19436364 | for (; i < co->co_nlocalsplus; i++) { |
| 9152 | assert((_PyLocals_GetKind(co->co_localspluskinds, i) & CO_FAST_FREE) != 0); | ||
| 9153 | 19436364 | PyObject *name = PyTuple_GET_ITEM(co->co_localsplusnames, i); | |
| 9154 | assert(PyUnicode_Check(name)); | ||
| 9155 |
1/2✓ Branch 1 taken 19436364 times.
✗ Branch 2 not taken.
|
19436364 | if (_PyUnicode_Equal(name, &_Py_ID(__class__))) { |
| 9156 | 19436364 | PyObject *cell = _PyFrame_GetLocalsArray(cframe)[i]; | |
| 9157 |
2/4✓ Branch 0 taken 19436364 times.
✗ Branch 1 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 19436364 times.
|
19436364 | if (cell == NULL || !PyCell_Check(cell)) { |
| 9158 | ✗ | PyErr_SetString(PyExc_RuntimeError, | |
| 9159 | "super(): bad __class__ cell"); | ||
| 9160 | ✗ | return -1; | |
| 9161 | } | ||
| 9162 | 19436364 | type = (PyTypeObject *) PyCell_GET(cell); | |
| 9163 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 19436364 times.
|
19436364 | if (type == NULL) { |
| 9164 | ✗ | PyErr_SetString(PyExc_RuntimeError, | |
| 9165 | "super(): empty __class__ cell"); | ||
| 9166 | ✗ | return -1; | |
| 9167 | } | ||
| 9168 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 19436364 times.
|
19436364 | if (!PyType_Check(type)) { |
| 9169 | ✗ | PyErr_Format(PyExc_RuntimeError, | |
| 9170 | "super(): __class__ is not a type (%s)", | ||
| 9171 | ✗ | Py_TYPE(type)->tp_name); | |
| 9172 | ✗ | return -1; | |
| 9173 | } | ||
| 9174 | 19436364 | break; | |
| 9175 | } | ||
| 9176 | } | ||
| 9177 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 19436364 times.
|
19436364 | if (type == NULL) { |
| 9178 | ✗ | PyErr_SetString(PyExc_RuntimeError, | |
| 9179 | "super(): __class__ cell not found"); | ||
| 9180 | ✗ | return -1; | |
| 9181 | } | ||
| 9182 | |||
| 9183 | 19436364 | *type_p = type; | |
| 9184 | 19436364 | *obj_p = firstarg; | |
| 9185 | 19436364 | return 0; | |
| 9186 | } | ||
| 9187 | |||
| 9188 | static int super_init_impl(PyObject *self, PyTypeObject *type, PyObject *obj); | ||
| 9189 | |||
| 9190 | static int | ||
| 9191 | ✗ | super_init(PyObject *self, PyObject *args, PyObject *kwds) | |
| 9192 | { | ||
| 9193 | ✗ | PyTypeObject *type = NULL; | |
| 9194 | ✗ | PyObject *obj = NULL; | |
| 9195 | |||
| 9196 | ✗ | if (!_PyArg_NoKeywords("super", kwds)) | |
| 9197 | ✗ | return -1; | |
| 9198 | ✗ | if (!PyArg_ParseTuple(args, "|O!O:super", &PyType_Type, &type, &obj)) | |
| 9199 | ✗ | return -1; | |
| 9200 | ✗ | if (super_init_impl(self, type, obj) < 0) { | |
| 9201 | ✗ | return -1; | |
| 9202 | } | ||
| 9203 | ✗ | return 0; | |
| 9204 | } | ||
| 9205 | |||
| 9206 | static inline int | ||
| 9207 | 63082538 | super_init_impl(PyObject *self, PyTypeObject *type, PyObject *obj) { | |
| 9208 | 63082538 | superobject *su = (superobject *)self; | |
| 9209 | 63082538 | PyTypeObject *obj_type = NULL; | |
| 9210 |
2/2✓ Branch 0 taken 19436364 times.
✓ Branch 1 taken 43646174 times.
|
63082538 | if (type == NULL) { |
| 9211 | /* Call super(), without args -- fill in from __class__ | ||
| 9212 | and first local variable on the stack. */ | ||
| 9213 | 19436364 | PyThreadState *tstate = _PyThreadState_GET(); | |
| 9214 | 19436364 | _PyInterpreterFrame *cframe = tstate->cframe->current_frame; | |
| 9215 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 19436364 times.
|
19436364 | if (cframe == NULL) { |
| 9216 | ✗ | PyErr_SetString(PyExc_RuntimeError, | |
| 9217 | "super(): no current frame"); | ||
| 9218 | ✗ | return -1; | |
| 9219 | } | ||
| 9220 | 19436364 | int res = super_init_without_args(cframe, cframe->f_code, &type, &obj); | |
| 9221 | |||
| 9222 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 19436364 times.
|
19436364 | if (res < 0) { |
| 9223 | ✗ | return -1; | |
| 9224 | } | ||
| 9225 | } | ||
| 9226 | |||
| 9227 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 63082538 times.
|
63082538 | if (obj == Py_None) |
| 9228 | ✗ | obj = NULL; | |
| 9229 |
1/2✓ Branch 0 taken 63082538 times.
✗ Branch 1 not taken.
|
63082538 | if (obj != NULL) { |
| 9230 | 63082538 | obj_type = supercheck(type, obj); | |
| 9231 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 63082538 times.
|
63082538 | if (obj_type == NULL) |
| 9232 | ✗ | return -1; | |
| 9233 | 63082538 | Py_INCREF(obj); | |
| 9234 | } | ||
| 9235 | 63082538 | Py_INCREF(type); | |
| 9236 | 63082538 | Py_XSETREF(su->type, type); | |
| 9237 | 63082538 | Py_XSETREF(su->obj, obj); | |
| 9238 | 63082538 | Py_XSETREF(su->obj_type, obj_type); | |
| 9239 | 63082538 | return 0; | |
| 9240 | } | ||
| 9241 | |||
| 9242 | PyDoc_STRVAR(super_doc, | ||
| 9243 | "super() -> same as super(__class__, <first argument>)\n" | ||
| 9244 | "super(type) -> unbound super object\n" | ||
| 9245 | "super(type, obj) -> bound super object; requires isinstance(obj, type)\n" | ||
| 9246 | "super(type, type2) -> bound super object; requires issubclass(type2, type)\n" | ||
| 9247 | "Typical use to call a cooperative superclass method:\n" | ||
| 9248 | "class C(B):\n" | ||
| 9249 | " def meth(self, arg):\n" | ||
| 9250 | " super().meth(arg)\n" | ||
| 9251 | "This works for class methods too:\n" | ||
| 9252 | "class C(B):\n" | ||
| 9253 | " @classmethod\n" | ||
| 9254 | " def cmeth(cls, arg):\n" | ||
| 9255 | " super().cmeth(arg)\n"); | ||
| 9256 | |||
| 9257 | static int | ||
| 9258 | 30520 | super_traverse(PyObject *self, visitproc visit, void *arg) | |
| 9259 | { | ||
| 9260 | 30520 | superobject *su = (superobject *)self; | |
| 9261 | |||
| 9262 |
2/4✓ Branch 0 taken 30520 times.
✗ Branch 1 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 30520 times.
|
30520 | Py_VISIT(su->obj); |
| 9263 |
2/4✓ Branch 0 taken 30520 times.
✗ Branch 1 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 30520 times.
|
30520 | Py_VISIT(su->type); |
| 9264 |
2/4✓ Branch 0 taken 30520 times.
✗ Branch 1 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 30520 times.
|
30520 | Py_VISIT(su->obj_type); |
| 9265 | |||
| 9266 | 30520 | return 0; | |
| 9267 | } | ||
| 9268 | |||
| 9269 | static PyObject * | ||
| 9270 | 63082538 | super_vectorcall(PyObject *self, PyObject *const *args, | |
| 9271 | size_t nargsf, PyObject *kwnames) | ||
| 9272 | { | ||
| 9273 | assert(PyType_Check(self)); | ||
| 9274 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 63082538 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
|
63082538 | if (!_PyArg_NoKwnames("super", kwnames)) { |
| 9275 | ✗ | return NULL; | |
| 9276 | } | ||
| 9277 | 63082538 | Py_ssize_t nargs = PyVectorcall_NARGS(nargsf); | |
| 9278 |
2/6✓ Branch 0 taken 63082538 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 63082538 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
|
63082538 | if (!_PyArg_CheckPositional("super()", nargs, 0, 2)) { |
| 9279 | ✗ | return NULL; | |
| 9280 | } | ||
| 9281 | 63082538 | PyTypeObject *type = NULL; | |
| 9282 | 63082538 | PyObject *obj = NULL; | |
| 9283 | 63082538 | PyTypeObject *self_type = (PyTypeObject *)self; | |
| 9284 | 63082538 | PyObject *su = self_type->tp_alloc(self_type, 0); | |
| 9285 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 63082538 times.
|
63082538 | if (su == NULL) { |
| 9286 | ✗ | return NULL; | |
| 9287 | } | ||
| 9288 | // 1 or 2 argument form super(). | ||
| 9289 |
2/2✓ Branch 0 taken 43646174 times.
✓ Branch 1 taken 19436364 times.
|
63082538 | if (nargs != 0) { |
| 9290 | 43646174 | PyObject *arg0 = args[0]; | |
| 9291 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 43646174 times.
|
43646174 | if (!PyType_Check(arg0)) { |
| 9292 | ✗ | PyErr_Format(PyExc_TypeError, | |
| 9293 | ✗ | "super() argument 1 must be a type, not %.200s", Py_TYPE(arg0)->tp_name); | |
| 9294 | ✗ | goto fail; | |
| 9295 | } | ||
| 9296 | 43646174 | type = (PyTypeObject *)arg0; | |
| 9297 | } | ||
| 9298 |
2/2✓ Branch 0 taken 43646174 times.
✓ Branch 1 taken 19436364 times.
|
63082538 | if (nargs == 2) { |
| 9299 | 43646174 | obj = args[1]; | |
| 9300 | } | ||
| 9301 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 63082538 times.
|
63082538 | if (super_init_impl(su, type, obj) < 0) { |
| 9302 | ✗ | goto fail; | |
| 9303 | } | ||
| 9304 | 63082538 | return su; | |
| 9305 | ✗ | fail: | |
| 9306 | ✗ | Py_DECREF(su); | |
| 9307 | ✗ | return NULL; | |
| 9308 | } | ||
| 9309 | |||
| 9310 | PyTypeObject PySuper_Type = { | ||
| 9311 | PyVarObject_HEAD_INIT(&PyType_Type, 0) | ||
| 9312 | "super", /* tp_name */ | ||
| 9313 | sizeof(superobject), /* tp_basicsize */ | ||
| 9314 | 0, /* tp_itemsize */ | ||
| 9315 | /* methods */ | ||
| 9316 | super_dealloc, /* tp_dealloc */ | ||
| 9317 | 0, /* tp_vectorcall_offset */ | ||
| 9318 | 0, /* tp_getattr */ | ||
| 9319 | 0, /* tp_setattr */ | ||
| 9320 | 0, /* tp_as_async */ | ||
| 9321 | super_repr, /* tp_repr */ | ||
| 9322 | 0, /* tp_as_number */ | ||
| 9323 | 0, /* tp_as_sequence */ | ||
| 9324 | 0, /* tp_as_mapping */ | ||
| 9325 | 0, /* tp_hash */ | ||
| 9326 | 0, /* tp_call */ | ||
| 9327 | 0, /* tp_str */ | ||
| 9328 | super_getattro, /* tp_getattro */ | ||
| 9329 | 0, /* tp_setattro */ | ||
| 9330 | 0, /* tp_as_buffer */ | ||
| 9331 | Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | | ||
| 9332 | Py_TPFLAGS_BASETYPE, /* tp_flags */ | ||
| 9333 | super_doc, /* tp_doc */ | ||
| 9334 | super_traverse, /* tp_traverse */ | ||
| 9335 | 0, /* tp_clear */ | ||
| 9336 | 0, /* tp_richcompare */ | ||
| 9337 | 0, /* tp_weaklistoffset */ | ||
| 9338 | 0, /* tp_iter */ | ||
| 9339 | 0, /* tp_iternext */ | ||
| 9340 | 0, /* tp_methods */ | ||
| 9341 | super_members, /* tp_members */ | ||
| 9342 | 0, /* tp_getset */ | ||
| 9343 | 0, /* tp_base */ | ||
| 9344 | 0, /* tp_dict */ | ||
| 9345 | super_descr_get, /* tp_descr_get */ | ||
| 9346 | 0, /* tp_descr_set */ | ||
| 9347 | 0, /* tp_dictoffset */ | ||
| 9348 | super_init, /* tp_init */ | ||
| 9349 | PyType_GenericAlloc, /* tp_alloc */ | ||
| 9350 | PyType_GenericNew, /* tp_new */ | ||
| 9351 | PyObject_GC_Del, /* tp_free */ | ||
| 9352 | .tp_vectorcall = (vectorcallfunc)super_vectorcall, | ||
| 9353 | }; | ||
| 9354 |